From cd9b55c70f081dbd004d347b51a793ce6fe3cacf Mon Sep 17 00:00:00 2001 From: Matthew Bouyack Date: Thu, 1 Jun 2017 14:37:29 -0700 Subject: Eliminate redundant changes to hardware vsync state. When transitioning between NORMAL and DOZE power modes we were redundantly calling resyncHardwareVsync. Similarly, when transitioning from DOZE_SUSPEND to OFF we were redundantly calling disableHardwareVsync. This change eliminates those redundant calls. Fixes bug 62235417 Change-Id: I513bbf94a7ab973ab258efe16436441ac2379b70 --- services/surfaceflinger/SurfaceFlinger.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7392006c6f..ee63ebcb9c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3210,7 +3210,8 @@ void SurfaceFlinger::setPowerModeInternal(const sp& hw, ALOGW("Couldn't set SCHED_OTHER on display off"); } - if (type == DisplayDevice::DISPLAY_PRIMARY) { + if (type == DisplayDevice::DISPLAY_PRIMARY && + currentMode != HWC_POWER_MODE_DOZE_SUSPEND) { disableHardwareVsync(true); // also cancels any in-progress resync // FIXME: eventthread only knows about the main display right now @@ -3224,7 +3225,8 @@ void SurfaceFlinger::setPowerModeInternal(const sp& hw, mode == HWC_POWER_MODE_NORMAL) { // Update display while dozing getHwComposer().setPowerMode(type, mode); - if (type == DisplayDevice::DISPLAY_PRIMARY) { + if (type == DisplayDevice::DISPLAY_PRIMARY && + currentMode == HWC_POWER_MODE_DOZE_SUSPEND) { // FIXME: eventthread only knows about the main display right now mEventThread->onScreenAcquired(); resyncToHardwareVsync(true); -- cgit v1.2.3-59-g8ed1b From 4ac0e7e66b9b8b8e76bc7f53399eb97201c11a7c Mon Sep 17 00:00:00 2001 From: Steven Thomas Date: Wed, 26 Jul 2017 18:48:28 -0700 Subject: 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 Merged-In: I17dc0e060bfb5cb447ffbaa573b279fc6d2d8bd1 --- libs/vr/libvrflinger/display_service.cpp | 10 +- libs/vr/libvrflinger/display_service.h | 3 - libs/vr/libvrflinger/hardware_composer.cpp | 352 +++++-------- libs/vr/libvrflinger/hardware_composer.h | 110 ++--- libs/vr/libvrflinger/include/dvr/vr_flinger.h | 3 - libs/vr/libvrflinger/vr_flinger.cpp | 4 - services/surfaceflinger/DisplayDevice.cpp | 6 +- .../surfaceflinger/DisplayHardware/ComposerHal.cpp | 4 + .../surfaceflinger/DisplayHardware/ComposerHal.h | 5 + services/surfaceflinger/DisplayHardware/HWC2.cpp | 549 +++++++++------------ services/surfaceflinger/DisplayHardware/HWC2.h | 124 +++-- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 131 +++-- .../surfaceflinger/DisplayHardware/HWComposer.h | 39 +- services/surfaceflinger/EventControlThread.cpp | 43 +- services/surfaceflinger/Layer.cpp | 50 +- services/surfaceflinger/Layer.h | 34 +- .../surfaceflinger/RenderEngine/RenderEngine.cpp | 33 +- .../surfaceflinger/RenderEngine/RenderEngine.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 294 +++++------ services/surfaceflinger/SurfaceFlinger.h | 60 ++- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 4 +- 21 files changed, 844 insertions(+), 1016 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') 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 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 { 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 { pdx::Status 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 #include +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 out_layers; std::vector 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=". - std::array 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(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(¤t_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 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 HardwareComposer::ComposerCallback::onHotplug( + Hwc2::Display /*display*/, + IComposerCallback::Connection /*conn*/) { + return Void(); } -void HardwareComposer::OnHardwareComposerRefresh() { - // TODO(steventhomas): Handle refresh. +Return HardwareComposer::ComposerCallback::onRefresh( + Hwc2::Display /*display*/) { + return hardware::Void(); } -void HardwareComposer::SetBacklightBrightness(int brightness) { - if (backlight_brightness_fd_) { - std::array text; - const int length = snprintf(text.data(), text.size(), "%d", brightness); - write(backlight_brightness_fd_.Get(), text.data(), length); +Return HardwareComposer::ComposerCallback::onVsync( + Hwc2::Display display, int64_t timestamp) { + if (display == HWC_DISPLAY_PRIMARY) { + std::lock_guard 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 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& 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& 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& 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()); 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()); 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::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()); } 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& 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& buffer, HWC::BlendMode blending, - HWC::Transform transform, HWC::Composition composition_type, - size_t z_order); + void Setup(const std::shared_ptr& 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 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 onRefresh(Hwc2::Display /*display*/) override { - return hardware::Void(); - } - - hardware::Return onVsync(Hwc2::Display /*display*/, - int64_t /*timestamp*/) override { - return hardware::Void(); - } + ComposerCallback(); + hardware::Return onHotplug(Hwc2::Display display, + Connection conn) override; + hardware::Return onRefresh(Hwc2::Display display) override; + hardware::Return 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 hidl_; + sp hidl_callback_; RequestDisplayCallback request_display_callback_; - sp 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 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& 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& 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 #include -extern "C" { - static void hotplug_hook(hwc2_callback_data_t callbackData, - hwc2_display_t displayId, int32_t intConnected) { - auto device = static_cast(callbackData); - auto display = device->getDisplayById(displayId); - if (display) { - auto connected = static_cast(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(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(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 onHotplug(Hwc2::Display display, + IComposerCallback::Connection conn) override + { + HWC2::Connection connection = static_cast(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 onRefresh(Hwc2::Display display) override + { + mCallback->onRefreshReceived(mSequenceId, display); + return Void(); + } + + Return 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(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(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(error)); - } - } +void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) { + if (mRegisteredCallback) { + ALOGW("Callback already registered. Ignored extra registration " + "attempt."); + return; } + mRegisteredCallback = true; + sp 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* 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( + *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual); + *outDisplay = display.get(); *format = static_cast(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( + &displayType)); + auto error = static_cast(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, Connection connected) -{ - if (connected == Connection::Connected) { - if (!display->isConnected()) { - mComposer->setClientTargetSlotCount(display->getId()); - display->loadConfigs(); - display->setConnected(true); + auto newDisplay = std::make_unique( + *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) -{ - 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, 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 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(*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 onHotplug(Hwc2::Display display, - Connection connected) override - { - hotplug_hook(mDevice, display, static_cast(connected)); - return Void(); - } - - Return onRefresh(Hwc2::Display display) override - { - refresh_hook(mDevice, display); - return Void(); - } - - Return onVsync(Hwc2::Display display, int64_t timestamp) override - { - vsync_hook(mDevice, display, timestamp); - return Void(); - } - -private: - Device* mDevice; -}; -} // namespace anonymous - -void Device::registerCallbacks() -{ - sp 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(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& 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(&mType)); - auto error = static_cast(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(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(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(intError); } -Error Display::createLayer(std::shared_ptr* 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(intError); if (error != Error::None) { return error; } - auto layer = std::make_shared(shared_from_this(), layerId); - mLayers.emplace(layerId, layer); - *outLayer = std::move(layer); + auto layer = std::make_unique( + 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(intError); if (error != Error::None) { @@ -430,12 +346,12 @@ Error Display::getActiveConfig( } Error Display::getChangedCompositionTypes( - std::unordered_map, Composition>* outTypes) + std::unordered_map* outTypes) { std::vector layerIds; std::vector 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(intError); error = static_cast(intError); @@ -464,7 +380,7 @@ Error Display::getChangedCompositionTypes( Error Display::getColorModes(std::vector* outModes) const { std::vector modes; - auto intError = mDevice.mComposer->getColorModes(mId, &modes); + auto intError = mComposer.getColorModes(mId, &modes); uint32_t numModes = modes.size(); auto error = static_cast(intError); if (error != Error::None) { @@ -489,19 +405,18 @@ std::vector> 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(intError); } Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests, - std::unordered_map, LayerRequest>* - outLayerRequests) + std::unordered_map* outLayerRequests) { uint32_t intDisplayRequests; std::vector layerIds; std::vector 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(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(intError); if (error != Error::None) { return error; @@ -552,7 +467,7 @@ Error Display::getHdrCapabilities( float maxAverageLuminance = -1.0f; float minLuminance = -1.0f; std::vector intTypes; - auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes, + auto intError = mComposer.getHdrCapabilities(mId, &intTypes, &maxLuminance, &maxAverageLuminance, &minLuminance); auto error = static_cast(intError); @@ -571,25 +486,24 @@ Error Display::getHdrCapabilities( } Error Display::getReleaseFences( - std::unordered_map, sp>* outFences) const + std::unordered_map>* outFences) const { std::vector layerIds; std::vector fenceFds; - auto intError = mDevice.mComposer->getReleaseFences(mId, - &layerIds, &fenceFds); + auto intError = mComposer.getReleaseFences(mId, &layerIds, &fenceFds); auto error = static_cast(intError); uint32_t numElements = layerIds.size(); if (error != Error::None) { return error; } - std::unordered_map, sp> releaseFences; + std::unordered_map> releaseFences; releaseFences.reserve(numElements); for (uint32_t element = 0; element < numElements; ++element) { auto layer = getLayerById(layerIds[element]); if (layer) { sp 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* outPresentFence) { int32_t presentFenceFd = -1; - auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd); + auto intError = mComposer.presentDisplay(mId, &presentFenceFd); auto error = static_cast(intError); if (error != Error::None) { return error; @@ -625,7 +539,7 @@ Error Display::setActiveConfig(const std::shared_ptr& 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(intError); } @@ -634,7 +548,7 @@ Error Display::setClientTarget(uint32_t slot, const sp& 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(dataspace), std::vector()); return static_cast(intError); @@ -642,15 +556,15 @@ Error Display::setClientTarget(uint32_t slot, const sp& target, Error Display::setColorMode(android_color_mode_t mode) { - auto intError = mDevice.mComposer->setColorMode(mId, - static_cast(mode)); + auto intError = mComposer.setColorMode( + mId, static_cast(mode)); return static_cast(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(hint)); return static_cast(intError); } @@ -660,7 +574,7 @@ Error Display::setOutputBuffer(const sp& 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(intError); } @@ -668,14 +582,14 @@ Error Display::setOutputBuffer(const sp& buffer, Error Display::setPowerMode(PowerMode mode) { auto intMode = static_cast(mode); - auto intError = mDevice.mComposer->setPowerMode(mId, intMode); + auto intError = mComposer.setPowerMode(mId, intMode); return static_cast(intError); } Error Display::setVsyncEnabled(Vsync enabled) { auto intEnabled = static_cast(enabled); - auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled); + auto intError = mComposer.setVsyncEnabled(mId, intEnabled); return static_cast(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(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(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(attribute), &value); auto error = static_cast(intError); @@ -760,7 +682,7 @@ void Display::loadConfigs() ALOGV("[%" PRIu64 "] loadConfigs", mId); std::vector configIds; - auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds); + auto intError = mComposer.getDisplayConfigs(mId, &configIds); auto error = static_cast(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(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 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, hwc2_layer_t id) - : mDisplay(display), - mDisplayId(display->getId()), - mDevice(display->getDevice()), - mId(id) +Layer::Layer(android::Hwc2::Composer& composer, + const std::unordered_set& 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(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 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(intError); } @@ -828,8 +747,8 @@ Error Layer::setBuffer(uint32_t slot, const sp& buffer, const sp& 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(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()); } 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(intError); @@ -861,24 +779,22 @@ Error Layer::setSurfaceDamage(const Region& damage) Error Layer::setBlendMode(BlendMode mode) { auto intMode = static_cast(mode); - auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId, - mId, intMode); + auto intError = mComposer.setLayerBlendMode(mDisplayId, mId, intMode); return static_cast(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(intError); } Error Layer::setCompositionType(Composition type) { auto intType = static_cast(type); - auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId, - mId, intType); + auto intError = mComposer.setLayerCompositionType( + mDisplayId, mId, intType); return static_cast(intError); } @@ -889,8 +805,7 @@ Error Layer::setDataspace(android_dataspace_t dataspace) } mDataSpace = dataspace; auto intDataspace = static_cast(dataspace); - auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId, - mId, intDataspace); + auto intError = mComposer.setLayerDataspace(mDisplayId, mId, intDataspace); return static_cast(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(intError); } Error Layer::setPlaneAlpha(float alpha) { - auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId, - mId, alpha); + auto intError = mComposer.setLayerPlaneAlpha(mDisplayId, mId, alpha); return static_cast(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(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(intError); } Error Layer::setTransform(Transform transform) { auto intTransform = static_cast(transform); - auto intError = mDevice.mComposer->setLayerTransform(mDisplayId, - mId, intTransform); + auto intError = mComposer.setLayerTransform(mDisplayId, mId, intTransform); return static_cast(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(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(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(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, Connection)> - HotplugCallback; -typedef std::function)> RefreshCallback; -typedef std::function, 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* 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, Connection connected); - void callRefresh(std::shared_ptr display); - void callVsync(std::shared_ptr 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 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 mComposer; - std::unordered_set mCapabilities; - std::unordered_map> mDisplays; - - HotplugCallback mHotplug; - std::vector, Connection>> - mPendingHotplugs; - RefreshCallback mRefresh; - std::vector> mPendingRefreshes; - VsyncCallback mVsync; - std::vector, nsecs_t>> mPendingVsyncs; + std::unordered_map> mDisplays; + bool mRegisteredCallback; }; // Convenience C++ class to access hwc2_device_t Display functions directly. -class Display : public std::enable_shared_from_this +class Display { public: - Display(Device& device, hwc2_display_t id); + Display(android::Hwc2::Composer& composer, + const std::unordered_set& 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* 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* outConfig) const; [[clang::warn_unused_result]] Error getChangedCompositionTypes( - std::unordered_map, Composition>* outTypes); + std::unordered_map* outTypes); [[clang::warn_unused_result]] Error getColorModes( std::vector* 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, LayerRequest>* - outLayerRequests); + std::unordered_map* 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* outCapabilities) const; [[clang::warn_unused_result]] Error getReleaseFences( - std::unordered_map, + std::unordered_map>* outFences) const; [[clang::warn_unused_result]] Error present( android::sp* 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 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& mCapabilities; + hwc2_display_t mId; bool mIsConnected; DisplayType mType; - std::unordered_map> mLayers; + std::unordered_map> mLayers; // The ordering in this map matters, for getConfigs(), when it is // converted to a vector std::map> mConfigs; @@ -301,12 +286,18 @@ private: class Layer { public: - Layer(const std::shared_ptr& display, hwc2_layer_t id); + Layer(android::Hwc2::Composer& composer, + const std::unordered_set& 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 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& buffer, @@ -333,11 +324,16 @@ public: [[clang::warn_unused_result]] Error setInfo(uint32_t type, uint32_t appId); private: - std::weak_ptr 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& mCapabilities; + hwc2_display_t mDisplayId; - Device& mDevice; hwc2_layer_t mId; android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN; + std::function 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(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(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& 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& /*display*/) { - mEventHandler->onInvalidateReceived(this); -} - -void HWComposer::vsync(const std::shared_ptr& 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& 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 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 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 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 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(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 HWComposer::getColorModes(int32_t displayId) c displayId); return modes; } - const std::shared_ptr& 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(error)); @@ -471,7 +456,7 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) { return UNKNOWN_ERROR; } if (state == 1) { //Present Succeeded. - std::unordered_map, sp> releaseFences; + std::unordered_map> 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, HWC2::Composition> - changedTypes; + std::unordered_map 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(0); - std::unordered_map, HWC2::LayerRequest> - layerRequests; + std::unordered_map layerRequests; layerRequests.reserve(numRequests); error = hwcDisplay->getRequests(&displayData.displayRequests, &layerRequests); @@ -598,7 +581,7 @@ sp HWComposer::getPresentFence(int32_t displayId) const { } sp HWComposer::getLayerReleaseFence(int32_t displayId, - const std::shared_ptr& 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, sp> releaseFences; + std::unordered_map> 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 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 getLayerReleaseFence(int32_t displayId, - const std::shared_ptr& 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& display); - void vsync(const std::shared_ptr& display, - int64_t timestamp); - void hotplug(const std::shared_ptr& display, - HWC2::Connection connected); - struct DisplayData { DisplayData(); ~DisplayData(); @@ -189,11 +180,10 @@ private: bool hasClientComposition; bool hasDeviceComposition; - std::shared_ptr hwcDisplay; + HWC2::Display* hwcDisplay; HWC2::DisplayRequest displayRequests; sp lastPresentFence; // signals when the last set op retires - std::unordered_map, sp> - releaseFences; + std::unordered_map> releaseFences; buffer_handle_t outbufHandle; sp outbufAcquireFence; mutable std::unordered_mapsetVsyncEnabled(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 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 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&& 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 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 609b15b382..0d93467125 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 vsyncSrc = new DispSyncSource(&mPrimaryDispSync, - vsyncPhaseOffsetNs, true, "app"); - mEventThread = new EventThread(vsyncSrc, *this, false); - sp 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, ¶m) != 0) { - ALOGE("Couldn't set SCHED_FIFO for SFEventThread"); - } - if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) { - ALOGE("Couldn't set SCHED_FIFO for EventThread"); - } + // start the EventThread + sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync, + vsyncPhaseOffsetNs, true, "app"); + mEventThread = new EventThread(vsyncSrc, *this, false); + sp 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, ¶m) != 0) { + ALOGE("Couldn't set SCHED_FIFO for SFEventThread"); + } + if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 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(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 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 = 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(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 requestMessage = new LambdaMessage([&]() { - sp hw(getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])); - setPowerModeInternal(hw, HWC_POWER_MODE_NORMAL); + sp 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& 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& 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& 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 #include #include #include +#include #include 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& hw, int mode); // called on the main thread in response to setPowerMode() +#ifdef USE_HWC2 + void setPowerModeInternal(const sp& hw, int mode, + bool stateLockHeld); +#else void setPowerModeInternal(const sp& hw, int mode); +#endif // Called on the main thread in response to setActiveColorMode() void setActiveColorModeInternal(const sp& hw, android_color_mode_t colorMode); @@ -591,13 +616,7 @@ private: /* ------------------------------------------------------------------------ * VrFlinger */ - template - 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 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 mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; -#ifdef USE_HWC2 - std::unique_ptr 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 mVrFlinger; std::atomic 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(this)); + mHwc.reset(new HWComposer(this, + *static_cast(this))); // get a RenderEngine for the given display / config (can't fail) mRenderEngine = RenderEngine::create(mEGLDisplay, -- cgit v1.2.3-59-g8ed1b From 0617894190ea0c3ee50889bee1d4df0f369b0761 Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 27 Jul 2017 10:25:59 -0700 Subject: Add a re-parent function to re-parent a specific child. This is similar to reparentChildren, but the reparentChild will only re-parent a specific child to the new parent and not all children. Test: Added test in Transaction_test for reparentChild. Change-Id: I4275e0d5f1d5601b489956753c78a56d1a5d4c1c --- libs/gui/LayerState.cpp | 4 +++ libs/gui/SurfaceComposerClient.cpp | 23 +++++++++++++ libs/gui/SurfaceControl.cpp | 7 ++++ libs/gui/include/gui/SurfaceComposerClient.h | 2 ++ libs/gui/include/gui/SurfaceControl.h | 6 ++++ libs/gui/include/private/gui/LayerState.h | 6 +++- services/surfaceflinger/Layer.cpp | 38 ++++++++++++++++++++++ services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 7 ++++ services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 7 ++++ services/surfaceflinger/tests/Transaction_test.cpp | 29 +++++++++++++++++ 11 files changed, 129 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 9b06e63610..573f6856d6 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -45,6 +45,8 @@ status_t layer_state_t::write(Parcel& output) const output.writeInt32(overrideScalingMode); output.writeStrongBinder(IInterface::asBinder(barrierGbp)); output.writeStrongBinder(relativeLayerHandle); + output.writeStrongBinder(parentHandleForChild); + output.writeStrongBinder(childHandle); output.write(transparentRegion); return NO_ERROR; } @@ -77,6 +79,8 @@ status_t layer_state_t::read(const Parcel& input) barrierGbp = interface_cast(input.readStrongBinder()); relativeLayerHandle = input.readStrongBinder(); + parentHandleForChild = input.readStrongBinder(); + childHandle = input.readStrongBinder(); input.read(transparentRegion); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 7ae2672249..b0ae7e0bdf 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -176,6 +176,9 @@ public: status_t reparentChildren(const sp& client, const sp& id, const sp& newParentHandle); + status_t reparentChild(const sp& client, + const sp& id, const sp& newParentHandle, + const sp& childHandle); status_t detachChildren(const sp& client, const sp& id); status_t setOverrideScalingMode(const sp& client, @@ -493,6 +496,21 @@ status_t Composer::reparentChildren( return NO_ERROR; } +status_t Composer::reparentChild(const sp& client, + const sp& id, + const sp& newParentHandle, + const sp& childHandle) { + Mutex::Autolock lock(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) { + return BAD_INDEX; + } + s->what |= layer_state_t::eReparentChild; + s->parentHandleForChild = newParentHandle; + s->childHandle = childHandle; + return NO_ERROR; +} + status_t Composer::detachChildren( const sp& client, const sp& id) { @@ -831,6 +849,11 @@ status_t SurfaceComposerClient::reparentChildren(const sp& id, return getComposer().reparentChildren(this, id, newParentHandle); } +status_t SurfaceComposerClient::reparentChild(const sp& id, + const sp& newParentHandle, const sp& childHandle) { + return getComposer().reparentChild(this, id, newParentHandle, childHandle); +} + status_t SurfaceComposerClient::detachChildren(const sp& id) { return getComposer().detachChildren(this, id); } diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 58bd273de6..b9c5ef9580 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -191,6 +191,13 @@ status_t SurfaceControl::reparentChildren(const sp& newParentHandle) { return mClient->reparentChildren(mHandle, newParentHandle); } +status_t SurfaceControl::reparentChild(const sp& newParentHandle, + const sp& childHandle) { + status_t err = validate(); + if (err < 0) return err; + return mClient->reparentChild(mHandle, newParentHandle, childHandle); +} + status_t SurfaceControl::detachChildren() { status_t err = validate(); if (err < 0) return err; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 145c0597bd..6e2cb83544 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -161,6 +161,8 @@ public: const sp& handle, uint64_t frameNumber); status_t reparentChildren(const sp& id, const sp& newParentHandle); + status_t reparentChild(const sp& id, const sp& newParentHandle, + const sp& childHandle); status_t detachChildren(const sp& id); status_t setOverrideScalingMode(const sp& id, int32_t overrideScalingMode); diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index c15209d32c..d8b67ef96a 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -124,6 +124,12 @@ public: // Reparents all children of this layer to the new parent handle. status_t reparentChildren(const sp& newParentHandle); + // Reparents a specified child from this layer to the new parent handle. + // The child, parent, and new parent must all have the same client. + // This can be used instead of reparentChildren if the caller wants to + // only re-parent specific children. + status_t reparentChild(const sp& newParentHandle, const sp& childHandle); + // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. // The child SurfaceControl's will not throw exceptions or return errors, diff --git a/libs/gui/include/private/gui/LayerState.h b/libs/gui/include/private/gui/LayerState.h index 307c764702..4f73e04e22 100644 --- a/libs/gui/include/private/gui/LayerState.h +++ b/libs/gui/include/private/gui/LayerState.h @@ -59,7 +59,8 @@ struct layer_state_t { eGeometryAppliesWithResize = 0x00001000, eReparentChildren = 0x00002000, eDetachChildren = 0x00004000, - eRelativeLayerChanged = 0x00008000 + eRelativeLayerChanged = 0x00008000, + eReparentChild = 0x00010000 }; layer_state_t() @@ -107,6 +108,9 @@ struct layer_state_t { sp relativeLayerHandle; + sp parentHandleForChild; + sp childHandle; + // non POD must be last. see write/read Region transparentRegion; }; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e92565fd9c..c406f74bc7 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2625,6 +2625,44 @@ bool Layer::reparentChildren(const sp& newParentHandle) { return true; } +bool Layer::reparentChild(const sp& newParentHandle, const sp& childHandle) { + if (newParentHandle == nullptr || childHandle == nullptr) { + return false; + } + + auto handle = static_cast(newParentHandle.get()); + sp newParent = handle->owner.promote(); + if (newParent == nullptr) { + ALOGE("Unable to promote Layer handle"); + return false; + } + + handle = static_cast(childHandle.get()); + sp child = handle->owner.promote(); + if (child == nullptr) { + ALOGE("Unable to promote child Layer handle"); + return false; + } + + if (mCurrentChildren.indexOf(child) < 0) { + ALOGE("Child layer is not child of current layer"); + return false; + } + + sp parentClient(mClientRef.promote()); + sp childClient(child->mClientRef.promote()); + sp newParentClient(newParent->mClientRef.promote()); + + if (parentClient != childClient || childClient != newParentClient) { + ALOGE("Current layer, child layer, and new parent layer must have the same client"); + return false; + } + + newParent->addChild(child); + mCurrentChildren.remove(child); + return true; +} + bool Layer::detachChildren() { traverseInZOrder(LayerVector::StateSet::Drawing, [this](Layer* child) { if (child == this) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f7b82e4fb7..f94833b32f 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -241,6 +241,7 @@ public: bool setOverrideScalingMode(int32_t overrideScalingMode); void setInfo(uint32_t type, uint32_t appId); bool reparentChildren(const sp& layer); + bool reparentChild(const sp& newParentHandle, const sp& childHandle); bool detachChildren(); // If we have received a new buffer this frame, we will pass its surface diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6a01f308a3..4b079d6fbb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3103,6 +3103,13 @@ uint32_t SurfaceFlinger::setClientStateLocked( // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } + // Always re-parent the children that explicitly requested to get + // re-parented before the general re-parent of all children. + if (what & layer_state_t::eReparentChild) { + if (layer->reparentChild(s.parentHandleForChild, s.childHandle)) { + flags |= eTransactionNeeded|eTraversalNeeded; + } + } if (what & layer_state_t::eReparentChildren) { if (layer->reparentChildren(s.reparentHandle)) { flags |= eTransactionNeeded|eTraversalNeeded; diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index a92e1f9f89..71aa52dee6 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -2679,6 +2679,13 @@ uint32_t SurfaceFlinger::setClientStateLocked( // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } + // Always re-parent the children that explicitly requested to get + // re-parented before the general re-parent of all children. + if (what & layer_state_t::eReparentChild) { + if (layer->reparentChild(s.parentHandleForChild, s.childHandle)) { + flags |= eTransactionNeeded|eTraversalNeeded; + } + } if (what & layer_state_t::eReparentChildren) { if (layer->reparentChildren(s.reparentHandle)) { flags |= eTransactionNeeded|eTraversalNeeded; diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 4ce14f8d3a..aef5a5f93b 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1123,4 +1123,33 @@ TEST_F(ChildLayerTest, Bug36858924) { fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0); } +TEST_F(ChildLayerTest, ReparentChild) { + SurfaceComposerClient::openGlobalTransaction(); + mChild->show(); + mChild->setPosition(10, 10); + mFGSurfaceControl->setPosition(64, 64); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + mFGSurfaceControl->reparentChild(mBGSurfaceControl->getHandle(), mChild->getHandle()); + { + ScreenCapture::captureScreen(&mCapture); + mCapture->expectFGColor(64, 64); + // In reparenting we should have exposed the entire foreground surface. + mCapture->expectFGColor(74, 74); + // And the child layer should now begin at 10, 10 (since the BG + // layer is at (0, 0)). + mCapture->expectBGColor(9, 9); + mCapture->expectChildColor(10, 10); + } +} + } -- cgit v1.2.3-59-g8ed1b From c9674336c053c071022279211eeffc6c9e7c1e99 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 28 Aug 2017 12:32:18 -0700 Subject: Traverse all layers to check if parent exists to add child layer. With the current implementation, when adding a child layer, the code only looks in the layersSortedByZ vector to see if the parent exists. The layersSortedByZ vector only contains the top most layers and not the child layers. The current behavior prevents creating child layers that have a parent that is also a child layer. This won't allow for nested child layers. Instead, traverse the list of layers, which will include looking at the child layers, to see if the parent layer exists. Test: NestedChildren test in Transaction_test Change-Id: I6c1a773b65e450010733f74f459fc327c7af3aea --- services/surfaceflinger/SurfaceFlinger.cpp | 9 ++++++++- services/surfaceflinger/tests/Transaction_test.cpp | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4b079d6fbb..2a9f923d3e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2777,7 +2777,14 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, if (parent == nullptr) { mCurrentState.layersSortedByZ.add(lbc); } else { - if (mCurrentState.layersSortedByZ.indexOf(parent) < 0) { + bool found = false; + mCurrentState.traverseInZOrder([&](Layer* layer) { + if (layer == parent.get()) { + found = true; + } + }); + + if (!found) { ALOGE("addClientLayer called with a removed parent"); return NAME_NOT_FOUND; } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index aef5a5f93b..d80ed92838 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1152,4 +1152,19 @@ TEST_F(ChildLayerTest, ReparentChild) { } } +TEST_F(ChildLayerTest, NestedChildren) { + sp grandchild = mComposerClient->createSurface( + String8("Grandchild surface"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mChild.get()); + fillSurfaceRGBA8(grandchild, 50, 50, 50); + + { + ScreenCapture::captureScreen(&mCapture); + // Expect the grandchild to begin at 64, 64 because it's a child of mChild layer + // which begins at 64, 64 + mCapture->checkPixel(64, 64, 50, 50, 50); + } +} + } -- cgit v1.2.3-59-g8ed1b From 039bbb8aca1280afdf0ecf20810c32804a82199d Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Wed, 6 Sep 2017 18:12:05 +0200 Subject: Use Layer.getAlpha instead of State.alpha to calculate occlusion Test: CP lock-free anim CL and make sure no black flickers when starting window fading out. Change-Id: I422f69e26ba86414476bae9cc3253caf062d4e36 --- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cae4deacb0..eb574ebf27 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2437,7 +2437,7 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa // compute the opaque region const int32_t layerOrientation = tr.getOrientation(); - if (s.alpha == 1.0f && !translucent && + if (layer->getAlpha() == 1.0f && !translucent && ((layerOrientation & Transform::ROT_INVALID) == false)) { // the opaque region is the layer's footprint opaqueRegion = visibleRegion; -- cgit v1.2.3-59-g8ed1b From f1961f713de2b3f54c8ce7653964b969e1a02bc8 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 18 Sep 2017 16:41:07 -0700 Subject: Re-parent invoked on child instead of on parent. The function to re-parent an individual child is now invoked on the child instead of the parent. This ensures the child ends up with the last parent set if multiple reparent requests are made in the same transaction. This also allows adding a parent to a layer that didn't have one previously. Test: Transaction_test -> Reparent, ReparentToNoParent, ReparentFromNoParent Change-Id: Idab429eb2dca5a4ae1b020a5a7629d719dd4d995 --- libs/gui/LayerState.cpp | 2 - libs/gui/SurfaceComposerClient.cpp | 19 +++--- libs/gui/SurfaceControl.cpp | 5 +- libs/gui/include/gui/SurfaceComposerClient.h | 3 +- libs/gui/include/gui/SurfaceControl.h | 7 +-- libs/gui/include/private/gui/LayerState.h | 3 +- services/surfaceflinger/Layer.cpp | 28 +++------ services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 6 +- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 6 +- services/surfaceflinger/tests/Transaction_test.cpp | 67 +++++++++++++++++++++- 11 files changed, 94 insertions(+), 54 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 573f6856d6..3418a4983e 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -46,7 +46,6 @@ status_t layer_state_t::write(Parcel& output) const output.writeStrongBinder(IInterface::asBinder(barrierGbp)); output.writeStrongBinder(relativeLayerHandle); output.writeStrongBinder(parentHandleForChild); - output.writeStrongBinder(childHandle); output.write(transparentRegion); return NO_ERROR; } @@ -80,7 +79,6 @@ status_t layer_state_t::read(const Parcel& input) interface_cast(input.readStrongBinder()); relativeLayerHandle = input.readStrongBinder(); parentHandleForChild = input.readStrongBinder(); - childHandle = input.readStrongBinder(); input.read(transparentRegion); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index b0ae7e0bdf..be7b1d2f6a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -176,9 +176,8 @@ public: status_t reparentChildren(const sp& client, const sp& id, const sp& newParentHandle); - status_t reparentChild(const sp& client, - const sp& id, const sp& newParentHandle, - const sp& childHandle); + status_t reparent(const sp& client, + const sp& id, const sp& newParentHandle); status_t detachChildren(const sp& client, const sp& id); status_t setOverrideScalingMode(const sp& client, @@ -496,18 +495,16 @@ status_t Composer::reparentChildren( return NO_ERROR; } -status_t Composer::reparentChild(const sp& client, +status_t Composer::reparent(const sp& client, const sp& id, - const sp& newParentHandle, - const sp& childHandle) { + const sp& newParentHandle) { Mutex::Autolock lock(mLock); layer_state_t* s = getLayerStateLocked(client, id); if (!s) { return BAD_INDEX; } - s->what |= layer_state_t::eReparentChild; + s->what |= layer_state_t::eReparent; s->parentHandleForChild = newParentHandle; - s->childHandle = childHandle; return NO_ERROR; } @@ -849,9 +846,9 @@ status_t SurfaceComposerClient::reparentChildren(const sp& id, return getComposer().reparentChildren(this, id, newParentHandle); } -status_t SurfaceComposerClient::reparentChild(const sp& id, - const sp& newParentHandle, const sp& childHandle) { - return getComposer().reparentChild(this, id, newParentHandle, childHandle); +status_t SurfaceComposerClient::reparent(const sp& id, + const sp& newParentHandle) { + return getComposer().reparent(this, id, newParentHandle); } status_t SurfaceComposerClient::detachChildren(const sp& id) { diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index b9c5ef9580..d801d12738 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -191,11 +191,10 @@ status_t SurfaceControl::reparentChildren(const sp& newParentHandle) { return mClient->reparentChildren(mHandle, newParentHandle); } -status_t SurfaceControl::reparentChild(const sp& newParentHandle, - const sp& childHandle) { +status_t SurfaceControl::reparent(const sp& newParentHandle) { status_t err = validate(); if (err < 0) return err; - return mClient->reparentChild(mHandle, newParentHandle, childHandle); + return mClient->reparent(mHandle, newParentHandle); } status_t SurfaceControl::detachChildren() { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6e2cb83544..cf2ff5b96e 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -161,8 +161,7 @@ public: const sp& handle, uint64_t frameNumber); status_t reparentChildren(const sp& id, const sp& newParentHandle); - status_t reparentChild(const sp& id, const sp& newParentHandle, - const sp& childHandle); + status_t reparent(const sp& id, const sp& newParentHandle); status_t detachChildren(const sp& id); status_t setOverrideScalingMode(const sp& id, int32_t overrideScalingMode); diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index d8b67ef96a..b506e00672 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -124,11 +124,10 @@ public: // Reparents all children of this layer to the new parent handle. status_t reparentChildren(const sp& newParentHandle); - // Reparents a specified child from this layer to the new parent handle. - // The child, parent, and new parent must all have the same client. + // Reparents the current layer to the new parent handle. The new parent must not be null. // This can be used instead of reparentChildren if the caller wants to - // only re-parent specific children. - status_t reparentChild(const sp& newParentHandle, const sp& childHandle); + // only re-parent a specific child. + status_t reparent(const sp& newParentHandle); // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. diff --git a/libs/gui/include/private/gui/LayerState.h b/libs/gui/include/private/gui/LayerState.h index 4f73e04e22..4ff2e5e0d6 100644 --- a/libs/gui/include/private/gui/LayerState.h +++ b/libs/gui/include/private/gui/LayerState.h @@ -60,7 +60,7 @@ struct layer_state_t { eReparentChildren = 0x00002000, eDetachChildren = 0x00004000, eRelativeLayerChanged = 0x00008000, - eReparentChild = 0x00010000 + eReparent = 0x00010000 }; layer_state_t() @@ -109,7 +109,6 @@ struct layer_state_t { sp relativeLayerHandle; sp parentHandleForChild; - sp childHandle; // non POD must be last. see write/read Region transparentRegion; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9435a187d9..fd30e1614b 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2625,8 +2625,8 @@ bool Layer::reparentChildren(const sp& newParentHandle) { return true; } -bool Layer::reparentChild(const sp& newParentHandle, const sp& childHandle) { - if (newParentHandle == nullptr || childHandle == nullptr) { +bool Layer::reparent(const sp& newParentHandle) { + if (newParentHandle == nullptr) { return false; } @@ -2637,29 +2637,19 @@ bool Layer::reparentChild(const sp& newParentHandle, const sp& return false; } - handle = static_cast(childHandle.get()); - sp child = handle->owner.promote(); - if (child == nullptr) { - ALOGE("Unable to promote child Layer handle"); - return false; - } - - if (mCurrentChildren.indexOf(child) < 0) { - ALOGE("Child layer is not child of current layer"); - return false; + sp parent = getParent(); + if (parent != nullptr) { + parent->removeChild(this); } + newParent->addChild(this); - sp parentClient(mClientRef.promote()); - sp childClient(child->mClientRef.promote()); + sp client(mClientRef.promote()); sp newParentClient(newParent->mClientRef.promote()); - if (parentClient != childClient || childClient != newParentClient) { - ALOGE("Current layer, child layer, and new parent layer must have the same client"); - return false; + if (client != newParentClient) { + client->setParentLayer(newParent); } - newParent->addChild(child); - mCurrentChildren.remove(child); return true; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f94833b32f..e7ece4579e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -241,7 +241,7 @@ public: bool setOverrideScalingMode(int32_t overrideScalingMode); void setInfo(uint32_t type, uint32_t appId); bool reparentChildren(const sp& layer); - bool reparentChild(const sp& newParentHandle, const sp& childHandle); + bool reparent(const sp& newParentHandle); bool detachChildren(); // If we have received a new buffer this frame, we will pass its surface diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cae4deacb0..6ee14fe72a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3121,10 +3121,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } - // Always re-parent the children that explicitly requested to get - // re-parented before the general re-parent of all children. - if (what & layer_state_t::eReparentChild) { - if (layer->reparentChild(s.parentHandleForChild, s.childHandle)) { + if (what & layer_state_t::eReparent) { + if (layer->reparent(s.parentHandleForChild)) { flags |= eTransactionNeeded|eTraversalNeeded; } } diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 71aa52dee6..1cf6ce33b7 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -2679,10 +2679,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } - // Always re-parent the children that explicitly requested to get - // re-parented before the general re-parent of all children. - if (what & layer_state_t::eReparentChild) { - if (layer->reparentChild(s.parentHandleForChild, s.childHandle)) { + if (what & layer_state_t::eReparent) { + if (layer->reparent(s.parentHandleForChild)) { flags |= eTransactionNeeded|eTraversalNeeded; } } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index dea6503e4e..21194926da 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1169,7 +1169,7 @@ TEST_F(ChildLayerTest, Bug36858924) { fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0); } -TEST_F(ChildLayerTest, ReparentChild) { +TEST_F(ChildLayerTest, Reparent) { SurfaceComposerClient::openGlobalTransaction(); mChild->show(); mChild->setPosition(10, 10); @@ -1185,7 +1185,7 @@ TEST_F(ChildLayerTest, ReparentChild) { // And 10 more pixels we should be back to the foreground surface mCapture->expectFGColor(84, 84); } - mFGSurfaceControl->reparentChild(mBGSurfaceControl->getHandle(), mChild->getHandle()); + mChild->reparent(mBGSurfaceControl->getHandle()); { ScreenCapture::captureScreen(&mCapture); mCapture->expectFGColor(64, 64); @@ -1198,6 +1198,69 @@ TEST_F(ChildLayerTest, ReparentChild) { } } +TEST_F(ChildLayerTest, ReparentToNoParent) { + SurfaceComposerClient::openGlobalTransaction(); + mChild->show(); + mChild->setPosition(10, 10); + mFGSurfaceControl->setPosition(64, 64); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + mChild->reparent(nullptr); + { + ScreenCapture::captureScreen(&mCapture); + // Nothing should have changed. + mCapture->expectFGColor(64, 64); + mCapture->expectChildColor(74, 74); + mCapture->expectFGColor(84, 84); + } +} + +TEST_F(ChildLayerTest, ReparentFromNoParent) { + sp newSurface = mComposerClient->createSurface( + String8("New Surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0); + ASSERT_TRUE(newSurface != NULL); + ASSERT_TRUE(newSurface->isValid()); + + fillSurfaceRGBA8(newSurface, 63, 195, 63); + SurfaceComposerClient::openGlobalTransaction(); + mChild->hide(); + newSurface->show(); + newSurface->setPosition(10, 10); + newSurface->setLayer(INT32_MAX-2); + mFGSurfaceControl->setPosition(64, 64); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // At 10, 10 we should see the new surface + mCapture->checkPixel(10, 10, 63, 195, 63); + } + + SurfaceComposerClient::openGlobalTransaction(); + newSurface->reparent(mFGSurfaceControl->getHandle()); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // newSurface will now be a child of mFGSurface so it will be 10, 10 offset from + // mFGSurface, putting it at 74, 74. + mCapture->expectFGColor(64, 64); + mCapture->checkPixel(74, 74, 63, 195, 63); + mCapture->expectFGColor(84, 84); + } +} + TEST_F(ChildLayerTest, NestedChildren) { sp grandchild = mComposerClient->createSurface( String8("Grandchild surface"), -- cgit v1.2.3-59-g8ed1b From fc2589e27981836d36b97ff19e85c84d8f50f915 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Thu, 21 Sep 2017 15:35:13 -0700 Subject: Single ATRACE_CALL per function Tracing was fixed in ag/1940080, which was later reverted. This change re-applies portion of the patch. Test: m -j Change-Id: I31cc126e6c222f6d8ae02803c037da773c9b8c4d --- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cae4deacb0..33278ae59e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1739,7 +1739,7 @@ void SurfaceFlinger::rebuildLayerStacks() { // rebuild the visible layer list per screen if (CC_UNLIKELY(mVisibleRegionsDirty)) { - ATRACE_CALL(); + ATRACE_NAME("rebuildLayerStacks VR Dirty"); mVisibleRegionsDirty = false; invalidateHwcGeometry(); -- cgit v1.2.3-59-g8ed1b From 13fdc49516d17f41e64e62e73c313b0928bf13cc Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 27 Jun 2017 12:40:18 -0700 Subject: Added native functionality to create a color layer. Added a new layer that can draw a specified color and specified alpha. This will replace creating a dim layer and allow any colors, not just black, to be set for this layer. Test: Added tests to Transaction_test.cpp to test with a color and a color layer with alpha. Change-Id: I00a38d1bbc01093026f088c3347454281bdc2b8c --- libs/gui/LayerDebugInfo.cpp | 20 ++++- libs/gui/LayerState.cpp | 6 ++ libs/gui/SurfaceComposerClient.cpp | 17 ++++ libs/gui/SurfaceControl.cpp | 5 ++ libs/gui/include/gui/ISurfaceComposerClient.h | 2 +- libs/gui/include/gui/LayerDebugInfo.h | 3 +- libs/gui/include/gui/SurfaceComposerClient.h | 2 + libs/gui/include/gui/SurfaceControl.h | 2 + libs/gui/include/private/gui/LayerState.h | 6 +- services/surfaceflinger/Android.mk | 2 +- services/surfaceflinger/ColorLayer.cpp | 66 +++++++++++++++ services/surfaceflinger/ColorLayer.h | 49 +++++++++++ services/surfaceflinger/Layer.cpp | 75 ++++++++--------- services/surfaceflinger/Layer.h | 24 ++---- services/surfaceflinger/LayerDim.cpp | 68 ---------------- services/surfaceflinger/LayerDim.h | 49 ----------- .../surfaceflinger/RenderEngine/Description.cpp | 14 +--- services/surfaceflinger/RenderEngine/Description.h | 9 +-- .../RenderEngine/GLES20RenderEngine.cpp | 50 ++---------- .../RenderEngine/GLES20RenderEngine.h | 9 +-- services/surfaceflinger/RenderEngine/Program.cpp | 8 +- services/surfaceflinger/RenderEngine/Program.h | 3 - .../surfaceflinger/RenderEngine/ProgramCache.cpp | 25 +++--- .../surfaceflinger/RenderEngine/ProgramCache.h | 10 +-- .../surfaceflinger/RenderEngine/RenderEngine.h | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 18 +++-- services/surfaceflinger/SurfaceFlinger.h | 4 +- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 25 +++--- services/surfaceflinger/SurfaceInterceptor.cpp | 2 +- .../tests/SurfaceFlinger_test.filter | 2 +- services/surfaceflinger/tests/Transaction_test.cpp | 94 ++++++++++++++++++++++ 31 files changed, 381 insertions(+), 296 deletions(-) create mode 100644 services/surfaceflinger/ColorLayer.cpp create mode 100644 services/surfaceflinger/ColorLayer.h delete mode 100644 services/surfaceflinger/LayerDim.cpp delete mode 100644 services/surfaceflinger/LayerDim.h (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp index 57ddde075a..d3dc16d30e 100644 --- a/libs/gui/LayerDebugInfo.cpp +++ b/libs/gui/LayerDebugInfo.cpp @@ -43,7 +43,10 @@ status_t LayerDebugInfo::writeToParcel(Parcel* parcel) const { RETURN_ON_ERROR(parcel->writeInt32(mHeight)); RETURN_ON_ERROR(parcel->write(mCrop)); RETURN_ON_ERROR(parcel->write(mFinalCrop)); - RETURN_ON_ERROR(parcel->writeFloat(mAlpha)); + RETURN_ON_ERROR(parcel->writeFloat(mColor.r)); + RETURN_ON_ERROR(parcel->writeFloat(mColor.g)); + RETURN_ON_ERROR(parcel->writeFloat(mColor.b)); + RETURN_ON_ERROR(parcel->writeFloat(mColor.a)); RETURN_ON_ERROR(parcel->writeUint32(mFlags)); RETURN_ON_ERROR(parcel->writeInt32(mPixelFormat)); RETURN_ON_ERROR(parcel->writeUint32(static_cast(mDataSpace))); @@ -79,7 +82,14 @@ status_t LayerDebugInfo::readFromParcel(const Parcel* parcel) { RETURN_ON_ERROR(parcel->readInt32(&mHeight)); RETURN_ON_ERROR(parcel->read(mCrop)); RETURN_ON_ERROR(parcel->read(mFinalCrop)); - RETURN_ON_ERROR(parcel->readFloat(&mAlpha)); + mColor.r = parcel->readFloat(); + RETURN_ON_ERROR(parcel->errorCheck()); + mColor.g = parcel->readFloat(); + RETURN_ON_ERROR(parcel->errorCheck()); + mColor.b = parcel->readFloat(); + RETURN_ON_ERROR(parcel->errorCheck()); + mColor.a = parcel->readFloat(); + RETURN_ON_ERROR(parcel->errorCheck()); RETURN_ON_ERROR(parcel->readUint32(&mFlags)); RETURN_ON_ERROR(parcel->readInt32(&mPixelFormat)); // \todo [2017-07-25 kraita]: Static casting mDataSpace pointer to an uint32 does work. Better ways? @@ -116,8 +126,10 @@ std::string to_string(const LayerDebugInfo& info) { result.appendFormat("isOpaque=%1d, invalidate=%1d, ", info.mIsOpaque, info.mContentDirty); result.appendFormat("dataspace=%s, ", dataspaceDetails(info.mDataSpace).c_str()); result.appendFormat("pixelformat=%s, ", decodePixelFormat(info.mPixelFormat).c_str()); - result.appendFormat("alpha=%.3f, flags=0x%08x, ", - static_cast(info.mAlpha), info.mFlags); + result.appendFormat("color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ", + static_cast(info.mColor.r), static_cast(info.mColor.g), + static_cast(info.mColor.b), static_cast(info.mColor.a), + info.mFlags); result.appendFormat("tr=[%.2f, %.2f][%.2f, %.2f]", static_cast(info.mMatrix[0][0]), static_cast(info.mMatrix[0][1]), static_cast(info.mMatrix[1][0]), static_cast(info.mMatrix[1][1])); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 3418a4983e..fcee73f445 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -46,6 +46,9 @@ status_t layer_state_t::write(Parcel& output) const output.writeStrongBinder(IInterface::asBinder(barrierGbp)); output.writeStrongBinder(relativeLayerHandle); output.writeStrongBinder(parentHandleForChild); + output.writeFloat(color.r); + output.writeFloat(color.g); + output.writeFloat(color.b); output.write(transparentRegion); return NO_ERROR; } @@ -79,6 +82,9 @@ status_t layer_state_t::read(const Parcel& input) interface_cast(input.readStrongBinder()); relativeLayerHandle = input.readStrongBinder(); parentHandleForChild = input.readStrongBinder(); + color.r = input.readFloat(); + color.g = input.readFloat(); + color.b = input.readFloat(); input.read(transparentRegion); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index be7b1d2f6a..c5a4389ae8 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -158,6 +158,8 @@ public: const Region& transparentRegion); status_t setAlpha(const sp& client, const sp& id, float alpha); + status_t setColor(const sp& client, const sp& id, + const half3& color); status_t setMatrix(const sp& client, const sp& id, float dsdx, float dtdx, float dtdy, float dsdy); status_t setOrientation(int orientation); @@ -402,6 +404,17 @@ status_t Composer::setAlpha(const sp& client, return NO_ERROR; } +status_t Composer::setColor(const sp& client, + const sp& id, const half3& color) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= layer_state_t::eColorChanged; + s->color = color; + return NO_ERROR; +} + status_t Composer::setLayerStack(const sp& client, const sp& id, uint32_t layerStack) { Mutex::Autolock _l(mLock); @@ -822,6 +835,10 @@ status_t SurfaceComposerClient::setAlpha(const sp& id, float alpha) { return getComposer().setAlpha(this, id, alpha); } +status_t SurfaceComposerClient::setColor(const sp& id, const half3& color) { + return getComposer().setColor(this, id, color); +} + status_t SurfaceComposerClient::setLayerStack(const sp& id, uint32_t layerStack) { return getComposer().setLayerStack(this, id, layerStack); } diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index d801d12738..9e1d7b6647 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -155,6 +155,11 @@ status_t SurfaceControl::setAlpha(float alpha) { if (err < 0) return err; return mClient->setAlpha(mHandle, alpha); } +status_t SurfaceControl::setColor(const half3& color) { + status_t err = validate(); + if (err < 0) return err; + return mClient->setColor(mHandle, color); +} status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) { status_t err = validate(); if (err < 0) return err; diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 2c613ea8c5..d5bbef25f8 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -41,7 +41,7 @@ public: eCursorWindow = 0x00002000, eFXSurfaceNormal = 0x00000000, - eFXSurfaceDim = 0x00020000, + eFXSurfaceColor = 0x00020000, eFXSurfaceMask = 0x000F0000, }; diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h index 8453e043ef..92bd8c5b28 100644 --- a/libs/gui/include/gui/LayerDebugInfo.h +++ b/libs/gui/include/gui/LayerDebugInfo.h @@ -22,6 +22,7 @@ #include #include +#include namespace android { @@ -52,7 +53,7 @@ public: int32_t mHeight = -1; Rect mCrop = Rect::INVALID_RECT; Rect mFinalCrop = Rect::INVALID_RECT; - float mAlpha = 0.f; + half4 mColor = half4(1.0_hf, 1.0_hf, 1.0_hf, 0.0_hf); uint32_t mFlags = 0; PixelFormat mPixelFormat = PIXEL_FORMAT_NONE; android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index cf2ff5b96e..17181430c7 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -32,6 +32,7 @@ #include #include +#include namespace android { @@ -149,6 +150,7 @@ public: status_t setRelativeLayer(const sp& id, const sp& relativeTo, int32_t layer); status_t setAlpha(const sp& id, float alpha=1.0f); + status_t setColor(const sp& id, const half3& color); status_t setMatrix(const sp& id, float dsdx, float dtdx, float dtdy, float dsdy); status_t setPosition(const sp& id, float x, float y); status_t setSize(const sp& id, uint32_t w, uint32_t h); diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index b506e00672..e98e26a391 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -29,6 +29,7 @@ #include #include +#include namespace android { @@ -90,6 +91,7 @@ public: status_t setFlags(uint32_t flags, uint32_t mask); status_t setTransparentRegionHint(const Region& transparent); status_t setAlpha(float alpha=1.0f); + status_t setColor(const half3& color); // Experimentarily it appears that the matrix transforms the // on-screen rectangle and it's contents before the position is diff --git a/libs/gui/include/private/gui/LayerState.h b/libs/gui/include/private/gui/LayerState.h index 4ff2e5e0d6..bd42634730 100644 --- a/libs/gui/include/private/gui/LayerState.h +++ b/libs/gui/include/private/gui/LayerState.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace android { @@ -60,7 +61,8 @@ struct layer_state_t { eReparentChildren = 0x00002000, eDetachChildren = 0x00004000, eRelativeLayerChanged = 0x00008000, - eReparent = 0x00010000 + eReparent = 0x00010000, + eColorChanged = 0x00020000 }; layer_state_t() @@ -110,6 +112,8 @@ struct layer_state_t { sp parentHandleForChild; + half3 color; + // non POD must be last. see write/read Region transparentRegion; }; diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 38529b6d0a..1f4427a11a 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -14,7 +14,7 @@ LOCAL_SRC_FILES := \ FrameTracker.cpp \ GpuService.cpp \ Layer.cpp \ - LayerDim.cpp \ + ColorLayer.cpp \ LayerRejecter.cpp \ LayerVector.cpp \ MessageQueue.cpp \ diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp new file mode 100644 index 0000000000..6923782b27 --- /dev/null +++ b/services/surfaceflinger/ColorLayer.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// #define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "ColorLayer" + +#include +#include +#include + +#include +#include + +#include + +#include "ColorLayer.h" +#include "SurfaceFlinger.h" +#include "DisplayDevice.h" +#include "RenderEngine/RenderEngine.h" + +namespace android { +// --------------------------------------------------------------------------- + +ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : Layer(flinger, client, name, w, h, flags) { +} + +void ColorLayer::onDraw(const sp& hw, + const Region& /* clip */, bool useIdentityTransform) const +{ + const State& s(getDrawingState()); + if (s.color.a>0) { + Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); + computeGeometry(hw, mesh, useIdentityTransform); + RenderEngine& engine(mFlinger->getRenderEngine()); + engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */, + true /* disableTexture */, s.color); + engine.drawMesh(mesh); + engine.disableBlending(); + } +} + +bool ColorLayer::isVisible() const { + const Layer::State& s(getDrawingState()); + return !isHiddenByPolicy() && s.color.a; +} + + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h new file mode 100644 index 0000000000..ac3e2a95dc --- /dev/null +++ b/services/surfaceflinger/ColorLayer.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_COLOR_LAYER_H +#define ANDROID_COLOR_LAYER_H + +#include +#include + +#include "Layer.h" + +// --------------------------------------------------------------------------- + +namespace android { + +class ColorLayer : public Layer +{ +public: + ColorLayer(SurfaceFlinger* flinger, const sp& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags); + virtual ~ColorLayer() = default; + + virtual const char* getTypeId() const { return "ColorLayer"; } + virtual void onDraw(const sp& hw, const Region& clip, + bool useIdentityTransform) const; + virtual bool isOpaque(const Layer::State&) const { return false; } + virtual bool isSecure() const { return false; } + virtual bool isFixedSize() const { return true; } + virtual bool isVisible() const; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_COLOR_LAYER_H diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index fd30e1614b..8734ee19fd 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -137,11 +137,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, mCurrentState.requestedFinalCrop = mCurrentState.finalCrop; mCurrentState.requestedCrop = mCurrentState.crop; mCurrentState.z = 0; -#ifdef USE_HWC2 - mCurrentState.alpha = 1.0f; -#else - mCurrentState.alpha = 0xFF; -#endif + mCurrentState.color.a = 1.0f; mCurrentState.layerStack = 0; mCurrentState.flags = layerFlags; mCurrentState.sequence = 0; @@ -334,6 +330,10 @@ const String8& Layer::getName() const { return mName; } +bool Layer::getPremultipledAlpha() const { + return mPremultipliedAlpha; +} + status_t Layer::setBuffers( uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { @@ -683,7 +683,7 @@ void Layer::setGeometry( " %s (%d)", mName.string(), to_string(blendMode).c_str(), to_string(error).c_str(), static_cast(error)); #else - if (!isOpaque(s) || getAlpha() != 0xFF) { + if (!isOpaque(s) || getAlpha() != 1.0f) { layer.setBlending(mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE); @@ -757,7 +757,7 @@ void Layer::setGeometry( hwcInfo.sourceCrop = sourceCrop; } - float alpha = getAlpha(); + float alpha = static_cast(getAlpha()); error = hwcLayer->setPlaneAlpha(alpha); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: " "%s (%d)", mName.string(), alpha, to_string(error).c_str(), @@ -787,7 +787,7 @@ void Layer::setGeometry( const Transform& tr(hw->getTransform()); layer.setFrame(tr.transform(frame)); layer.setCrop(computeCrop(hw)); - layer.setPlaneAlpha(getAlpha()); + layer.setPlaneAlpha(static_cast(std::round(255.0f*getAlpha()))); #endif /* @@ -904,8 +904,11 @@ void Layer::setPerFrameData(const sp& displayDevice) { if (mActiveBuffer == nullptr) { setCompositionType(hwcId, HWC2::Composition::SolidColor); - // For now, we only support black for DimLayer - error = hwcLayer->setColor({0, 0, 0, 255}); + half4 color = getColor(); + error = hwcLayer->setColor({static_cast(std::round(255.0f*color.r)), + static_cast(std::round(255.0f * color.g)), + static_cast(std::round(255.0f * color.b)), + 255}); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), static_cast(error)); @@ -1254,7 +1257,8 @@ void Layer::drawWithOpenGL(const sp& hw, texCoords[3] = vec2(right, 1.0f - top); RenderEngine& engine(mFlinger->getRenderEngine()); - engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha()); + engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), + false /* disableTexture */, getColor()); #ifdef USE_HWC2 engine.setSourceDataSpace(mCurrentState.dataSpace); #endif @@ -1877,19 +1881,30 @@ bool Layer::setSize(uint32_t w, uint32_t h) { setTransactionFlags(eTransactionNeeded); return true; } -#ifdef USE_HWC2 bool Layer::setAlpha(float alpha) { -#else -bool Layer::setAlpha(uint8_t alpha) { -#endif - if (mCurrentState.alpha == alpha) + if (mCurrentState.color.a == alpha) return false; mCurrentState.sequence++; - mCurrentState.alpha = alpha; + mCurrentState.color.a = alpha; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } + +bool Layer::setColor(const half3& color) { + if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g + && color.b == mCurrentState.color.b) + return false; + + mCurrentState.sequence++; + mCurrentState.color.r = color.r; + mCurrentState.color.g = color.g; + mCurrentState.color.b = color.b; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) { mCurrentState.sequence++; mCurrentState.requested.transform.set( @@ -2141,13 +2156,8 @@ bool Layer::isHiddenByPolicy() const { } bool Layer::isVisible() const { -#ifdef USE_HWC2 return !(isHiddenByPolicy()) && getAlpha() > 0.0f && (mActiveBuffer != NULL || mSidebandStream != NULL); -#else - return !(isHiddenByPolicy()) && getAlpha() - && (mActiveBuffer != NULL || mSidebandStream != NULL); -#endif } bool Layer::allTransactionsSignaled() { @@ -2439,7 +2449,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mHeight = ds.active.h; info.mCrop = ds.crop; info.mFinalCrop = ds.finalCrop; - info.mAlpha = ds.alpha; + info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); info.mDataSpace = getDataSpace(); @@ -2467,7 +2477,6 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mContentDirty = contentDirty; return info; } - #ifdef USE_HWC2 void Layer::miniDumpHeader(String8& result) { result.append("----------------------------------------"); @@ -2791,23 +2800,17 @@ Transform Layer::getTransform() const { return t * getDrawingState().active.transform; } -#ifdef USE_HWC2 -float Layer::getAlpha() const { +half Layer::getAlpha() const { const auto& p = mDrawingParent.promote(); - float parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0; - return parentAlpha * getDrawingState().alpha; + half parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0_hf; + return parentAlpha * getDrawingState().color.a; } -#else -uint8_t Layer::getAlpha() const { - const auto& p = mDrawingParent.promote(); - float parentAlpha = (p != nullptr) ? (p->getAlpha() / 255.0f) : 1.0; - float drawingAlpha = getDrawingState().alpha / 255.0f; - drawingAlpha = drawingAlpha * parentAlpha; - return static_cast(std::round(drawingAlpha * 255)); +half4 Layer::getColor() const { + const half4 color(getDrawingState().color); + return half4(color.r, color.g, color.b, getAlpha()); } -#endif void Layer::commitChildList() { for (size_t i = 0; i < mCurrentChildren.size(); i++) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index e7ece4579e..921492b210 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -51,6 +51,8 @@ #include "RenderEngine/Mesh.h" #include "RenderEngine/Texture.h" +#include + namespace android { // --------------------------------------------------------------------------- @@ -119,11 +121,6 @@ public: // to achieve mirroring. uint32_t layerStack; -#ifdef USE_HWC2 - float alpha; -#else - uint8_t alpha; -#endif uint8_t flags; uint8_t mask; uint8_t reserved[2]; @@ -158,6 +155,8 @@ public: // A list of surfaces whose Z-order is interpreted relative to ours. SortedVector> zOrderRelatives; + + half4 color; }; // ----------------------------------------------------------------------- @@ -225,11 +224,8 @@ public: bool setLayer(int32_t z); bool setRelativeLayer(const sp& relativeToHandle, int32_t relativeZ); -#ifdef USE_HWC2 bool setAlpha(float alpha); -#else - bool setAlpha(uint8_t alpha); -#endif + bool setColor(const half3& color); bool setTransparentRegionHint(const Region& transparent); bool setFlags(uint8_t flags, uint8_t mask); bool setLayerStack(uint32_t layerStack); @@ -509,11 +505,8 @@ public: // Returns the Alpha of the Surface, accounting for the Alpha // of parent Surfaces in the hierarchy (alpha's will be multiplied // down the hierarchy). -#ifdef USE_HWC2 - float getAlpha() const; -#else - uint8_t getAlpha() const; -#endif + half getAlpha() const; + half4 getColor() const; void traverseInReverseZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); @@ -683,9 +676,8 @@ public: sp getProducer() const; const String8& getName() const; void notifyAvailableFrames(); - PixelFormat getPixelFormat() const { return mFormat; } - + bool getPremultipledAlpha() const; private: // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp deleted file mode 100644 index daebf8abcd..0000000000 --- a/services/surfaceflinger/LayerDim.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// #define LOG_NDEBUG 0 -#undef LOG_TAG -#define LOG_TAG "LayerDim" - -#include -#include -#include - -#include -#include - -#include - -#include "LayerDim.h" -#include "SurfaceFlinger.h" -#include "DisplayDevice.h" -#include "RenderEngine/RenderEngine.h" - -namespace android { -// --------------------------------------------------------------------------- - -LayerDim::LayerDim(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags) - : Layer(flinger, client, name, w, h, flags) { -} - -LayerDim::~LayerDim() { -} - -void LayerDim::onDraw(const sp& hw, - const Region& /* clip */, bool useIdentityTransform) const -{ - const State& s(getDrawingState()); - if (s.alpha>0) { - Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); - computeGeometry(hw, mesh, useIdentityTransform); - RenderEngine& engine(mFlinger->getRenderEngine()); - engine.setupDimLayerBlending(s.alpha); - engine.drawMesh(mesh); - engine.disableBlending(); - } -} - -bool LayerDim::isVisible() const { - const Layer::State& s(getDrawingState()); - return !isHiddenByPolicy() && s.alpha; -} - - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h deleted file mode 100644 index a0cfca98cf..0000000000 --- a/services/surfaceflinger/LayerDim.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_DIM_H -#define ANDROID_LAYER_DIM_H - -#include -#include - -#include "Layer.h" - -// --------------------------------------------------------------------------- - -namespace android { - -class LayerDim : public Layer -{ -public: - LayerDim(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags); - virtual ~LayerDim(); - - virtual const char* getTypeId() const { return "LayerDim"; } - virtual void onDraw(const sp& hw, const Region& clip, - bool useIdentityTransform) const; - virtual bool isOpaque(const Layer::State&) const { return false; } - virtual bool isSecure() const { return false; } - virtual bool isFixedSize() const { return true; } - virtual bool isVisible() const; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_DIM_H diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp index effd3191c8..706960cafe 100644 --- a/services/surfaceflinger/RenderEngine/Description.cpp +++ b/services/surfaceflinger/RenderEngine/Description.cpp @@ -27,22 +27,15 @@ namespace android { Description::Description() { - mPlaneAlpha = 1.0f; mPremultipliedAlpha = false; mOpaque = true; mTextureEnabled = false; mColorMatrixEnabled = false; - - memset(mColor, 0, sizeof(mColor)); } Description::~Description() { } -void Description::setPlaneAlpha(GLclampf planeAlpha) { - mPlaneAlpha = planeAlpha; -} - void Description::setPremultipliedAlpha(bool premultipliedAlpha) { mPremultipliedAlpha = premultipliedAlpha; } @@ -60,11 +53,8 @@ void Description::disableTexture() { mTextureEnabled = false; } -void Description::setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { - mColor[0] = red; - mColor[1] = green; - mColor[2] = blue; - mColor[3] = alpha; +void Description::setColor(const half4& color) { + mColor = color; } void Description::setProjectionMatrix(const mat4& mtx) { diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h index 3beffdf9e1..cbac855ff3 100644 --- a/services/surfaceflinger/RenderEngine/Description.h +++ b/services/surfaceflinger/RenderEngine/Description.h @@ -35,8 +35,6 @@ class Description { friend class Program; friend class ProgramCache; - // value of the plane-alpha, between 0 and 1 - GLclampf mPlaneAlpha; // whether textures are premultiplied bool mPremultipliedAlpha; // whether this layer is marked as opaque @@ -46,8 +44,8 @@ class Description { Texture mTexture; bool mTextureEnabled; - // color used when texturing is disabled - GLclampf mColor[4]; + // color used when texturing is disabled or when setting alpha. + half4 mColor; // projection matrix mat4 mProjectionMatrix; @@ -60,12 +58,11 @@ public: Description(); ~Description(); - void setPlaneAlpha(GLclampf planeAlpha); void setPremultipliedAlpha(bool premultipliedAlpha); void setOpaque(bool opaque); void setTexture(const Texture& texture); void disableTexture(); - void setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void setColor(const half4& color); void setProjectionMatrix(const mat4& mtx); void setColorMatrix(const mat4& mtx); const mat4& getColorMatrix() const; diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 37a530b33a..daaa11e1d3 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -204,25 +204,17 @@ void GLES20RenderEngine::setViewportAndProjection( mVpHeight = vph; } -#ifdef USE_HWC2 void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, - bool opaque, float alpha) { -#else -void GLES20RenderEngine::setupLayerBlending( - bool premultipliedAlpha, bool opaque, int alpha) { -#endif - + bool opaque, bool disableTexture, const half4& color) { mState.setPremultipliedAlpha(premultipliedAlpha); mState.setOpaque(opaque); -#ifdef USE_HWC2 - mState.setPlaneAlpha(alpha); + mState.setColor(color); - if (alpha < 1.0f || !opaque) { -#else - mState.setPlaneAlpha(alpha / 255.0f); + if (disableTexture) { + mState.disableTexture(); + } - if (alpha < 0xFF || !opaque) { -#endif + if (color.a < 1.0f || !opaque) { glEnable(GL_BLEND); glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else { @@ -230,33 +222,6 @@ void GLES20RenderEngine::setupLayerBlending( } } -#ifdef USE_HWC2 -void GLES20RenderEngine::setupDimLayerBlending(float alpha) { -#else -void GLES20RenderEngine::setupDimLayerBlending(int alpha) { -#endif - mState.setPlaneAlpha(1.0f); - mState.setPremultipliedAlpha(true); - mState.setOpaque(false); -#ifdef USE_HWC2 - mState.setColor(0, 0, 0, alpha); -#else - mState.setColor(0, 0, 0, alpha/255.0f); -#endif - mState.disableTexture(); - -#ifdef USE_HWC2 - if (alpha == 1.0f) { -#else - if (alpha == 0xFF) { -#endif - glDisable(GL_BLEND); - } else { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } -} - #ifdef USE_HWC2 void GLES20RenderEngine::setColorMode(android_color_mode mode) { ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode); @@ -355,10 +320,9 @@ void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) { } void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) { - mState.setPlaneAlpha(1.0f); mState.setPremultipliedAlpha(true); mState.setOpaque(false); - mState.setColor(r, g, b, a); + mState.setColor(half4(r, g, b, a)); mState.disableTexture(); glDisable(GL_BLEND); } diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index eaf94af54c..5ac12fc3d6 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -68,10 +68,9 @@ protected: virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation); -#ifdef USE_HWC2 virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, - float alpha) override; - virtual void setupDimLayerBlending(float alpha) override; + bool disableTexture, const half4& color) override; +#ifdef USE_HWC2 // Color management related functions and state void setColorMode(android_color_mode mode); @@ -92,10 +91,6 @@ protected: // Currently only supporting sRGB and DisplayP3 color spaces mat4 mSrgbToDisplayP3; -#else - virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, - int alpha); - virtual void setupDimLayerBlending(int alpha); #endif bool mPlatformHasWideColor = false; diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp index 48a8da5e8e..e95a6c573b 100644 --- a/services/surfaceflinger/RenderEngine/Program.cpp +++ b/services/surfaceflinger/RenderEngine/Program.cpp @@ -22,6 +22,7 @@ #include "Program.h" #include "ProgramCache.h" #include "Description.h" +#include namespace android { @@ -63,7 +64,6 @@ Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const c mTextureMatrixLoc = glGetUniformLocation(programId, "texture"); mSamplerLoc = glGetUniformLocation(programId, "sampler"); mColorLoc = glGetUniformLocation(programId, "color"); - mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane"); // set-up the default values for our uniforms glUseProgram(programId); @@ -132,11 +132,9 @@ void Program::setUniforms(const Description& desc) { glUniform1i(mSamplerLoc, 0); glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix().asArray()); } - if (mAlphaPlaneLoc >= 0) { - glUniform1f(mAlphaPlaneLoc, desc.mPlaneAlpha); - } if (mColorLoc >= 0) { - glUniform4fv(mColorLoc, 1, desc.mColor); + const float* color = &static_cast const &>(desc.mColor)[0]; + glUniform4fv(mColorLoc, 1, color); } if (mColorMatrixLoc >= 0) { glUniformMatrix4fv(mColorMatrixLoc, 1, GL_FALSE, desc.mColorMatrix.asArray()); diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/Program.h index 36bd120e39..a2ae2ee007 100644 --- a/services/surfaceflinger/RenderEngine/Program.h +++ b/services/surfaceflinger/RenderEngine/Program.h @@ -79,9 +79,6 @@ private: /* location of the sampler uniform */ GLint mSamplerLoc; - /* location of the alpha plane uniform */ - GLint mAlphaPlaneLoc; - /* location of the color uniform */ GLint mColorLoc; }; diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index 06b225299c..b4375454cc 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -89,7 +89,7 @@ ProgramCache::~ProgramCache() { void ProgramCache::primeCache() { uint32_t shaderCount = 0; uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK | - Key::PLANE_ALPHA_MASK | Key::TEXTURE_MASK; + Key::ALPHA_MASK | Key::TEXTURE_MASK; // Prime the cache for all combinations of the above masks, // leaving off the experimental color matrix mask options. @@ -122,8 +122,8 @@ ProgramCache::Key ProgramCache::computeKey(const Description& description) { description.mTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES ? Key::TEXTURE_EXT : description.mTexture.getTextureTarget() == GL_TEXTURE_2D ? Key::TEXTURE_2D : Key::TEXTURE_OFF) - .set(Key::PLANE_ALPHA_MASK, - (description.mPlaneAlpha < 1) ? Key::PLANE_ALPHA_LT_ONE : Key::PLANE_ALPHA_EQ_ONE) + .set(Key::ALPHA_MASK, + (description.mColor.a < 1) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE) .set(Key::BLEND_MASK, description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL) .set(Key::OPACITY_MASK, @@ -168,12 +168,12 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { } else if (needs.getTextureTarget() == Key::TEXTURE_2D) { fs << "uniform sampler2D sampler;" << "varying vec2 outTexCoords;"; - } else if (needs.getTextureTarget() == Key::TEXTURE_OFF) { - fs << "uniform vec4 color;"; } - if (needs.hasPlaneAlpha()) { - fs << "uniform float alphaPlane;"; + + if (needs.getTextureTarget() == Key::TEXTURE_OFF || needs.hasAlpha()) { + fs << "uniform vec4 color;"; } + if (needs.hasColorMatrix()) { fs << "uniform mat4 colorMatrix;"; } @@ -225,18 +225,19 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { if (needs.isTexturing()) { fs << "gl_FragColor = texture2D(sampler, outTexCoords);"; } else { - fs << "gl_FragColor = color;"; + fs << "gl_FragColor.rgb = color.rgb;"; + fs << "gl_FragColor.a = 1.0;"; } if (needs.isOpaque()) { fs << "gl_FragColor.a = 1.0;"; } - if (needs.hasPlaneAlpha()) { - // modulate the alpha value with planeAlpha + if (needs.hasAlpha()) { + // modulate the current alpha value with alpha set if (needs.isPremultiplied()) { // ... and the color too if we're premultiplied - fs << "gl_FragColor *= alphaPlane;"; + fs << "gl_FragColor *= color.a;"; } else { - fs << "gl_FragColor.a *= alphaPlane;"; + fs << "gl_FragColor.a *= color.a;"; } } diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h index 5b0fbcd153..ff5cf0f21a 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.h +++ b/services/surfaceflinger/RenderEngine/ProgramCache.h @@ -57,9 +57,9 @@ public: OPACITY_TRANSLUCENT = 0x00000000, OPACITY_MASK = 0x00000002, - PLANE_ALPHA_LT_ONE = 0x00000004, - PLANE_ALPHA_EQ_ONE = 0x00000000, - PLANE_ALPHA_MASK = 0x00000004, + ALPHA_LT_ONE = 0x00000004, + ALPHA_EQ_ONE = 0x00000000, + ALPHA_MASK = 0x00000004, TEXTURE_OFF = 0x00000000, TEXTURE_EXT = 0x00000008, @@ -95,8 +95,8 @@ public: inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; } - inline bool hasPlaneAlpha() const { - return (mKey & PLANE_ALPHA_MASK) == PLANE_ALPHA_LT_ONE; + inline bool hasAlpha() const { + return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; } inline bool hasColorMatrix() const { return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON; diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 954457946e..fa65979edd 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -25,6 +25,7 @@ #include #include #include +#include #define EGL_NO_CONFIG ((EGLConfig)0) @@ -98,16 +99,13 @@ public: virtual void checkErrors() const; virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation) = 0; + virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, + bool disableTexture, const half4& color) = 0; #ifdef USE_HWC2 - virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, float alpha) = 0; - virtual void setupDimLayerBlending(float alpha) = 0; virtual void setColorMode(android_color_mode mode) = 0; virtual void setSourceDataSpace(android_dataspace source) = 0; virtual void setWideColor(bool hasWideColor) = 0; virtual bool usesWideColor() = 0; -#else - virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0; - virtual void setupDimLayerBlending(int alpha) = 0; #endif virtual void setupLayerTexturing(const Texture& texture) = 0; virtual void setupLayerBlackedOut() = 0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e21379cd70..a7e7008b20 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -73,7 +73,7 @@ #include "EventThread.h" #include "Layer.h" #include "LayerVector.h" -#include "LayerDim.h" +#include "ColorLayer.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" @@ -2725,7 +2725,7 @@ bool SurfaceFlinger::doComposeSurfaces( case HWC2::Composition::SolidColor: { const Layer::State& state(layer->getDrawingState()); if (layer->getClearClientTarget(hwcId) && !firstLayer && - layer->isOpaque(state) && (state.alpha == 1.0f) + layer->isOpaque(state) && (state.color.a == 1.0f) && hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared @@ -3065,6 +3065,10 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (layer->setAlpha(s.alpha)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eColorChanged) { + if (layer->setColor(s.color)) + flags |= eTraversalNeeded; + } if (what & layer_state_t::eMatrixChanged) { if (layer->setMatrix(s.matrix)) flags |= eTraversalNeeded; @@ -3168,8 +3172,8 @@ status_t SurfaceFlinger::createLayer( uniqueName, w, h, flags, format, handle, gbp, &layer); break; - case ISurfaceComposerClient::eFXSurfaceDim: - result = createDimLayer(client, + case ISurfaceComposerClient::eFXSurfaceColor: + result = createColorLayer(client, uniqueName, w, h, flags, handle, gbp, &layer); break; @@ -3251,11 +3255,11 @@ status_t SurfaceFlinger::createNormalLayer(const sp& client, return err; } -status_t SurfaceFlinger::createDimLayer(const sp& client, +status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* handle, sp* gbp, sp* outLayer) { - *outLayer = new LayerDim(this, client, name, w, h, flags); + *outLayer = new ColorLayer(this, client, name, w, h, flags); *handle = (*outLayer)->getHandle(); *gbp = (*outLayer)->getProducer(); return NO_ERROR; @@ -4594,7 +4598,7 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", layer->isVisible() ? '+' : '-', i, layer->getName().string(), layer->getLayerStack(), state.z, - layer->isVisible(), state.flags, state.alpha); + layer->isVisible(), state.flags, static_cast(state.color.a)); i++; }); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 1b77aafc58..e87d35f912 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -84,7 +84,7 @@ class Client; class DisplayEventConnection; class EventThread; class Layer; -class LayerDim; +class ColorLayer; class Surface; class RenderEngine; class EventControlThread; @@ -410,7 +410,7 @@ private: sp* outHandle, sp* outGbp, sp* outLayer); - status_t createDimLayer(const sp& client, const String8& name, + status_t createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* outHandle, sp* outGbp, sp* outLayer); diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index b1c8c0ab69..b0021383ff 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -71,7 +71,7 @@ #include "EventThread.h" #include "Layer.h" #include "LayerVector.h" -#include "LayerDim.h" +#include "ColorLayer.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" @@ -2024,7 +2024,7 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa // compute the opaque region const int32_t layerOrientation = tr.getOrientation(); - if (s.alpha==255 && !translucent && + if (layer->getAlpha()==1.0f && !translucent && ((layerOrientation & Transform::ROT_INVALID) == false)) { // the opaque region is the layer's footprint opaqueRegion = visibleRegion; @@ -2297,7 +2297,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const const Layer::State& state(layer->getDrawingState()); if ((cur->getHints() & HWC_HINT_CLEAR_FB) && i - && layer->isOpaque(state) && (state.alpha == 0xFF) + && layer->isOpaque(state) && (state.color.a == 1.0f) && hasGlesComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared @@ -2622,9 +2622,14 @@ uint32_t SurfaceFlinger::setClientStateLocked( } } if (what & layer_state_t::eAlphaChanged) { - if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f))) + if (layer->setAlpha(s.alpha)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eColorChanged) { + if (layer->setColor(s.color)) { + flags |= eTraversalNeeded; + } + } if (what & layer_state_t::eMatrixChanged) { if (layer->setMatrix(s.matrix)) flags |= eTraversalNeeded; @@ -2728,8 +2733,8 @@ status_t SurfaceFlinger::createLayer( uniqueName, w, h, flags, format, handle, gbp, &layer); break; - case ISurfaceComposerClient::eFXSurfaceDim: - result = createDimLayer(client, + case ISurfaceComposerClient::eFXSurfaceColor: + result = createColorLayer(client, uniqueName, w, h, flags, handle, gbp, &layer); break; @@ -2804,11 +2809,11 @@ status_t SurfaceFlinger::createNormalLayer(const sp& client, return err; } -status_t SurfaceFlinger::createDimLayer(const sp& client, +status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* handle, sp* gbp, sp* outLayer) { - *outLayer = new LayerDim(this, client, name, w, h, flags); + *outLayer = new ColorLayer(this, client, name, w, h, flags); *handle = (*outLayer)->getHandle(); *gbp = (*outLayer)->getProducer(); return NO_ERROR; @@ -4089,10 +4094,10 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ && state.z <= maxLayerZ) { layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%x", + ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", layer->isVisible() ? '+' : '-', i, layer->getName().string(), layer->getLayerStack(), state.z, - layer->isVisible(), state.flags, state.alpha); + layer->isVisible(), state.flags, static_cast(state.color.a)); i++; }); } diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index db489b2456..eeb492978c 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -98,7 +98,7 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(), layer->mCurrentState.active.transform.ty()); addDepthLocked(transaction, layerId, layer->mCurrentState.z); - addAlphaLocked(transaction, layerId, layer->mCurrentState.alpha); + addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a); addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion); addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack); addCropLocked(transaction, layerId, layer->mCurrentState.crop); diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter index 6be708ad1c..5c188dc8a5 100644 --- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter +++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter @@ -1,5 +1,5 @@ { "presubmit": { - "filter": "LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*" + "filter": "LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:LayerColorTest.*" } } \ No newline at end of file diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 21194926da..8900a4d258 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -28,6 +28,7 @@ #include #include +#include namespace android { @@ -1276,4 +1277,97 @@ TEST_F(ChildLayerTest, NestedChildren) { } } +class LayerColorTest : public LayerUpdateTest { + protected: + void SetUp() override { + LayerUpdateTest::SetUp(); + + mLayerColorControl = mComposerClient->createSurface( + String8("Layer color surface"), + 128, 128, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor); + + ASSERT_TRUE(mLayerColorControl != NULL); + ASSERT_TRUE(mLayerColorControl->isValid()); + + SurfaceComposerClient::openGlobalTransaction(); + ASSERT_EQ(NO_ERROR, mLayerColorControl->setLayer(INT32_MAX-1)); + ASSERT_EQ(NO_ERROR, mLayerColorControl->setPosition(140, 140)); + ASSERT_EQ(NO_ERROR, mLayerColorControl->hide()); + ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide()); + SurfaceComposerClient::closeGlobalTransaction(true); + } + + void TearDown() override { + LayerUpdateTest::TearDown(); + mLayerColorControl = 0; + } + + sp mLayerColorControl; +}; + +TEST_F(LayerColorTest, ColorLayerNoAlpha) { + sp sc; + + { + SCOPED_TRACE("before setColor"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(145, 145); + } + + + SurfaceComposerClient::openGlobalTransaction(); + half3 color(43.0f/255.0f, 207.0f/255.0f, 131.0f/255.0f); + mLayerColorControl->setColor(color); + mLayerColorControl->show(); + SurfaceComposerClient::closeGlobalTransaction(true); + { + // There should now be a color + SCOPED_TRACE("after setColor"); + ScreenCapture::captureScreen(&sc); + sc->checkPixel(145, 145, 43, 207, 131); + } +} + +TEST_F(LayerColorTest, ColorLayerWithAlpha) { + sp sc; + { + SCOPED_TRACE("before setColor"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(145, 145); + } + + SurfaceComposerClient::openGlobalTransaction(); + half3 color(43.0f/255.0f, 207.0f/255.0f, 131.0f/255.0f); + mLayerColorControl->setColor(color); + mLayerColorControl->setAlpha(.75f); + mLayerColorControl->show(); + SurfaceComposerClient::closeGlobalTransaction(true); + { + // There should now be a color with .75 alpha + SCOPED_TRACE("after setColor"); + ScreenCapture::captureScreen(&sc); + sc->checkPixel(145, 145, 48, 171, 147); + } +} + +TEST_F(LayerColorTest, ColorLayerWithNoColor) { + sp sc; + { + SCOPED_TRACE("before setColor"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(145, 145); + } + + SurfaceComposerClient::openGlobalTransaction(); + mLayerColorControl->show(); + SurfaceComposerClient::closeGlobalTransaction(true); + { + // There should now be set to 0,0,0 (black) as default. + SCOPED_TRACE("after setColor"); + ScreenCapture::captureScreen(&sc); + sc->checkPixel(145, 145, 0, 0, 0); + } +} + } -- cgit v1.2.3-59-g8ed1b From deb36f24f43fdbd83c5c61d40b9a32d091ac2a37 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 5 Oct 2017 20:35:18 -0700 Subject: Support priority based dumpsys in surface flinger Call dump with no args when called with CRITICAL priority. Register service with support for critical priority dumps. BUG: 31774394 Test: adb bugreport ~/tmp.zip Test: adb shell dumpsys --priority CRITICAL Test: mmm -j32 frameworks/native/services/utils && \ adb sync data && adb shell /data/nativetest/prioritydumper_test/prioritydumper_test && \ adb shell /data/nativetest64/prioritydumper_test/prioritydumper_test && \ printf "\n\n#### ALL TESTS PASSED ####\n" Change-Id: I29140808493eb7c8805bfa338ab9a335154862b4 --- services/surfaceflinger/Android.bp | 2 + services/surfaceflinger/Android.mk | 8 ++- services/surfaceflinger/SurfaceFlinger.cpp | 3 +- services/surfaceflinger/SurfaceFlinger.h | 13 ++++- services/surfaceflinger/main_surfaceflinger.cpp | 3 +- services/utils/Android.bp | 1 - services/utils/PriorityDumper.cpp | 29 +++++++--- services/utils/include/PriorityDumper.h | 62 ---------------------- .../utils/include/serviceutils/PriorityDumper.h | 59 ++++++++++++++++++++ services/utils/tests/Android.bp | 3 -- services/utils/tests/PriorityDumper_test.cpp | 43 ++++++++------- 11 files changed, 124 insertions(+), 102 deletions(-) delete mode 100644 services/utils/include/PriorityDumper.h create mode 100644 services/utils/include/serviceutils/PriorityDumper.h (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 4775e4ef54..64a2a509ab 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -1,6 +1,8 @@ cc_library_static { name: "libsurfaceflingerincludes", export_include_dirs: ["."], + static_libs = ["libserviceutils"], + export_static_lib_headers = ["libserviceutils"], } subdirs = ["tests/fakehwc"] \ No newline at end of file diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 1f4427a11a..390263ff2e 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -67,7 +67,10 @@ LOCAL_STATIC_LIBRARIES := \ libtrace_proto \ libvkjson \ libvr_manager \ - libvrflinger + libvrflinger \ + libserviceutils + +LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libserviceutils LOCAL_SHARED_LIBRARIES := \ android.frameworks.vr.composer@1.0 \ @@ -145,7 +148,8 @@ LOCAL_SHARED_LIBRARIES := \ libdl LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain -LOCAL_STATIC_LIBRARIES := libtrace_proto +LOCAL_STATIC_LIBRARIES := libtrace_proto \ + libserviceutils LOCAL_MODULE := surfaceflinger diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f04cb884c3..5982422658 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3459,8 +3459,7 @@ void SurfaceFlinger::setPowerMode(const sp& display, int mode) { // --------------------------------------------------------------------------- -status_t SurfaceFlinger::dump(int fd, const Vector& args) -{ +status_t SurfaceFlinger::doDump(int fd, const Vector& args) { String8 result; IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e87d35f912..47ad7b93f2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -47,6 +47,8 @@ #include +#include + #include #include @@ -105,6 +107,7 @@ enum { }; class SurfaceFlinger : public BnSurfaceComposer, + public PriorityDumper, private IBinder::DeathRecipient, #ifdef USE_HWC2 private HWC2::ComposerCallback @@ -272,7 +275,7 @@ private: */ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - virtual status_t dump(int fd, const Vector& args); + virtual status_t dump(int fd, const Vector& args) { return priorityDump(fd, args); } /* ------------------------------------------------------------------------ * ISurfaceComposer interface @@ -592,6 +595,13 @@ private: /* ------------------------------------------------------------------------ * Debugging & dumpsys */ +public: + status_t dumpCritical(int fd, const Vector& /*args*/) { + return doDump(fd, Vector()); + } + + status_t dumpAll(int fd, const Vector& args) { return doDump(fd, args); } +private: void listLayersLocked(const Vector& args, size_t& index, String8& result) const; void dumpStatsLocked(const Vector& args, size_t& index, String8& result) const; void clearStatsLocked(const Vector& args, size_t& index, String8& result); @@ -616,6 +626,7 @@ private: bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; } + status_t doDump(int fd, const Vector& args); #ifdef USE_HWC2 /* ------------------------------------------------------------------------ diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index e50f3ce1f9..6a24891b08 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -105,7 +105,8 @@ int main(int, char**) { // publish surface flinger sp sm(defaultServiceManager()); - sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false); + sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false, + IServiceManager::DUMP_PRIORITY_CRITICAL); // publish GpuService sp gpuservice = new GpuService(); diff --git a/services/utils/Android.bp b/services/utils/Android.bp index 467349153f..6132956eeb 100644 --- a/services/utils/Android.bp +++ b/services/utils/Android.bp @@ -20,7 +20,6 @@ cc_library_static { cflags: [ "-Wall", - "-Wno-unused-parameter", "-Werror", ], diff --git a/services/utils/PriorityDumper.cpp b/services/utils/PriorityDumper.cpp index 555cf03bf0..9851188b46 100644 --- a/services/utils/PriorityDumper.cpp +++ b/services/utils/PriorityDumper.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "include/PriorityDumper.h" +#include "include/serviceutils/PriorityDumper.h" namespace android { @@ -25,22 +25,35 @@ static void getStrippedArgs(Vector& dest, const Vector& sour } } -void priorityDump(PriorityDumper& dumper, int fd, const Vector& args) { +status_t PriorityDumper::dumpAll(int fd, const Vector& args) { + status_t status; + status = dumpCritical(fd, args); + if (status != OK) return status; + status = dumpHigh(fd, args); + if (status != OK) return status; + status = dumpNormal(fd, args); + if (status != OK) return status; + return status; +} + +status_t PriorityDumper::priorityDump(int fd, const Vector& args) { + status_t status; if (args.size() >= 2 && args[0] == PRIORITY_ARG) { String16 priority = args[1]; Vector strippedArgs; getStrippedArgs(strippedArgs, args, 2); if (priority == PRIORITY_ARG_CRITICAL) { - dumper.dumpCritical(fd, strippedArgs); + status = dumpCritical(fd, strippedArgs); } else if (priority == PRIORITY_ARG_HIGH) { - dumper.dumpHigh(fd, strippedArgs); + status = dumpHigh(fd, strippedArgs); } else if (priority == PRIORITY_ARG_NORMAL) { - dumper.dumpNormal(fd, strippedArgs); + status = dumpNormal(fd, strippedArgs); } else { - dumper.dump(fd, args); + status = dumpAll(fd, args); } } else { - dumper.dump(fd, args); + status = dumpAll(fd, args); } + return status; } -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/utils/include/PriorityDumper.h b/services/utils/include/PriorityDumper.h deleted file mode 100644 index 23e900d90e..0000000000 --- a/services/utils/include/PriorityDumper.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_UTILS_PRIORITYDUMP_H -#define ANDROID_UTILS_PRIORITYDUMP_H - -#include -#include - -namespace android { - -constexpr const char16_t PRIORITY_ARG[] = u"--dump-priority"; -constexpr const char16_t PRIORITY_ARG_CRITICAL[] = u"CRITICAL"; -constexpr const char16_t PRIORITY_ARG_HIGH[] = u"HIGH"; -constexpr const char16_t PRIORITY_ARG_NORMAL[] = u"NORMAL"; - -// Helper class to split dumps into various priority buckets. -class PriorityDumper { -public: - // Dumps CRITICAL priority sections. - virtual void dumpCritical(int fd, const Vector& args) {} - - // Dumps HIGH priority sections. - virtual void dumpHigh(int fd, const Vector& args) {} - - // Dumps normal priority sections. - virtual void dumpNormal(int fd, const Vector& args) {} - - // Dumps all sections. - // This method is called when priorityDump is called without priority - // arguments. By default, it calls all three dump methods. - virtual void dump(int fd, const Vector& args) { - dumpCritical(fd, args); - dumpHigh(fd, args); - dumpNormal(fd, args); - } - virtual ~PriorityDumper() = default; -}; - -// Parses the argument list checking if the first argument is --dump_priority and -// the second argument is the priority type (HIGH, CRITICAL or NORMAL). If the -// arguments are found, they are stripped and the appropriate PriorityDumper -// method is called. -// If --dump_priority argument is not passed, all supported sections are dumped. -void priorityDump(PriorityDumper& dumper, int fd, const Vector& args); - -}; // namespace android - -#endif // ANDROID_UTILS_PRIORITYDUMP_H diff --git a/services/utils/include/serviceutils/PriorityDumper.h b/services/utils/include/serviceutils/PriorityDumper.h new file mode 100644 index 0000000000..0319242404 --- /dev/null +++ b/services/utils/include/serviceutils/PriorityDumper.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_UTILS_PRIORITYDUMPER_H +#define ANDROID_UTILS_PRIORITYDUMPER_H + +#include +#include +#include + +namespace android { + +constexpr const char16_t PRIORITY_ARG[] = u"--dump-priority"; +constexpr const char16_t PRIORITY_ARG_CRITICAL[] = u"CRITICAL"; +constexpr const char16_t PRIORITY_ARG_HIGH[] = u"HIGH"; +constexpr const char16_t PRIORITY_ARG_NORMAL[] = u"NORMAL"; + +// Helper class to split dumps into various priority buckets. +class PriorityDumper { +public: + // Parses the argument list checking if the first argument is --dump_priority and + // the second argument is the priority type (HIGH, CRITICAL or NORMAL). If the + // arguments are found, they are stripped and the appropriate PriorityDumper + // method is called. + // If --dump_priority argument is not passed, all supported sections are dumped. + status_t priorityDump(int fd, const Vector& args); + + // Dumps CRITICAL priority sections. + virtual status_t dumpCritical(int /*fd*/, const Vector& /*args*/) { return OK; } + + // Dumps HIGH priority sections. + virtual status_t dumpHigh(int /*fd*/, const Vector& /*args*/) { return OK; } + + // Dumps normal priority sections. + virtual status_t dumpNormal(int /*fd*/, const Vector& /*args*/) { return OK; } + + // Dumps all sections. + // This method is called when priorityDump is called without priority + // arguments. By default, it calls all three dump methods. + virtual status_t dumpAll(int fd, const Vector& args); + virtual ~PriorityDumper() = default; +}; + +} // namespace android + +#endif // ANDROID_UTILS_PRIORITYDUMPER_H diff --git a/services/utils/tests/Android.bp b/services/utils/tests/Android.bp index 5a9dc0a333..15829fa12b 100644 --- a/services/utils/tests/Android.bp +++ b/services/utils/tests/Android.bp @@ -21,9 +21,6 @@ cc_test { shared_libs: [ "libutils", ], - cflags: [ - "-Wno-unused-parameter", - ], static_libs = [ "libgmock", "libserviceutils" diff --git a/services/utils/tests/PriorityDumper_test.cpp b/services/utils/tests/PriorityDumper_test.cpp index c5a121e3fc..79e7340878 100644 --- a/services/utils/tests/PriorityDumper_test.cpp +++ b/services/utils/tests/PriorityDumper_test.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "PriorityDumper.h" +#include "serviceutils/PriorityDumper.h" #include @@ -32,17 +32,17 @@ using ::testing::Test; class PriorityDumperMock : public PriorityDumper { public: - MOCK_METHOD2(dumpCritical, void(int, const Vector&)); - MOCK_METHOD2(dumpHigh, void(int, const Vector&)); - MOCK_METHOD2(dumpNormal, void(int, const Vector&)); - MOCK_METHOD2(dump, void(int, const Vector&)); + MOCK_METHOD2(dumpCritical, status_t(int, const Vector&)); + MOCK_METHOD2(dumpHigh, status_t(int, const Vector&)); + MOCK_METHOD2(dumpNormal, status_t(int, const Vector&)); + MOCK_METHOD2(dumpAll, status_t(int, const Vector&)); }; class DumpAllMock : public PriorityDumper { public: - MOCK_METHOD2(dumpCritical, void(int, const Vector&)); - MOCK_METHOD2(dumpHigh, void(int, const Vector&)); - MOCK_METHOD2(dumpNormal, void(int, const Vector&)); + MOCK_METHOD2(dumpCritical, status_t(int, const Vector&)); + MOCK_METHOD2(dumpHigh, status_t(int, const Vector&)); + MOCK_METHOD2(dumpNormal, status_t(int, const Vector&)); }; class PriorityDumperTest : public Test { @@ -61,15 +61,15 @@ static void addAll(Vector& av, const std::vector& v) { TEST_F(PriorityDumperTest, noArgsPassed) { Vector args; - EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); - priorityDump(dumper_, fd, args); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, noPriorityArgsPassed) { Vector args; addAll(args, {"bunch", "of", "args"}); - EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); - priorityDump(dumper_, fd, args); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, priorityArgsOnly) { @@ -77,8 +77,7 @@ TEST_F(PriorityDumperTest, priorityArgsOnly) { addAll(args, {"--dump-priority", "CRITICAL"}); Vector strippedArgs; EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs))); - - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, dumpCritical) { @@ -88,7 +87,7 @@ TEST_F(PriorityDumperTest, dumpCritical) { addAll(strippedArgs, {"args", "left", "behind"}); EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs))); - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, dumpHigh) { @@ -98,7 +97,7 @@ TEST_F(PriorityDumperTest, dumpHigh) { addAll(strippedArgs, {"args", "left", "behind"}); EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs))); - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, dumpNormal) { @@ -108,7 +107,7 @@ TEST_F(PriorityDumperTest, dumpNormal) { addAll(strippedArgs, {"args", "left", "behind"}); EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs))); - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, dumpAll) { @@ -119,21 +118,21 @@ TEST_F(PriorityDumperTest, dumpAll) { EXPECT_CALL(dumpAlldumper_, dumpHigh(fd, ElementsAreArray(args))); EXPECT_CALL(dumpAlldumper_, dumpNormal(fd, ElementsAreArray(args))); - priorityDump(dumpAlldumper_, fd, args); + dumpAlldumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, priorityArgWithPriorityMissing) { Vector args; addAll(args, {"--dump-priority"}); - EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, priorityArgWithInvalidPriority) { Vector args; addAll(args, {"--dump-priority", "REALLY_HIGH"}); - EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 91a86774805069c853edbb2adb5033ca43621497 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 6 Oct 2017 21:31:25 +0000 Subject: Revert "Support priority based dumpsys in surface flinger" This reverts commit deb36f24f43fdbd83c5c61d40b9a32d091ac2a37. Reason for revert: fixing git_master/mini_emulator_x86-userdebug break Change-Id: I4729bcb0f4c6ee1f388b916666a0ddbf8a5da5bd --- services/surfaceflinger/Android.bp | 2 - services/surfaceflinger/Android.mk | 8 +-- services/surfaceflinger/SurfaceFlinger.cpp | 3 +- services/surfaceflinger/SurfaceFlinger.h | 13 +---- services/surfaceflinger/main_surfaceflinger.cpp | 3 +- services/utils/Android.bp | 1 + services/utils/PriorityDumper.cpp | 29 +++------- services/utils/include/PriorityDumper.h | 62 ++++++++++++++++++++++ .../utils/include/serviceutils/PriorityDumper.h | 59 -------------------- services/utils/tests/Android.bp | 3 ++ services/utils/tests/PriorityDumper_test.cpp | 43 +++++++-------- 11 files changed, 102 insertions(+), 124 deletions(-) create mode 100644 services/utils/include/PriorityDumper.h delete mode 100644 services/utils/include/serviceutils/PriorityDumper.h (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 64a2a509ab..4775e4ef54 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -1,8 +1,6 @@ cc_library_static { name: "libsurfaceflingerincludes", export_include_dirs: ["."], - static_libs = ["libserviceutils"], - export_static_lib_headers = ["libserviceutils"], } subdirs = ["tests/fakehwc"] \ No newline at end of file diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 390263ff2e..1f4427a11a 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -67,10 +67,7 @@ LOCAL_STATIC_LIBRARIES := \ libtrace_proto \ libvkjson \ libvr_manager \ - libvrflinger \ - libserviceutils - -LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libserviceutils + libvrflinger LOCAL_SHARED_LIBRARIES := \ android.frameworks.vr.composer@1.0 \ @@ -148,8 +145,7 @@ LOCAL_SHARED_LIBRARIES := \ libdl LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain -LOCAL_STATIC_LIBRARIES := libtrace_proto \ - libserviceutils +LOCAL_STATIC_LIBRARIES := libtrace_proto LOCAL_MODULE := surfaceflinger diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5982422658..f04cb884c3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3459,7 +3459,8 @@ void SurfaceFlinger::setPowerMode(const sp& display, int mode) { // --------------------------------------------------------------------------- -status_t SurfaceFlinger::doDump(int fd, const Vector& args) { +status_t SurfaceFlinger::dump(int fd, const Vector& args) +{ String8 result; IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 47ad7b93f2..e87d35f912 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -47,8 +47,6 @@ #include -#include - #include #include @@ -107,7 +105,6 @@ enum { }; class SurfaceFlinger : public BnSurfaceComposer, - public PriorityDumper, private IBinder::DeathRecipient, #ifdef USE_HWC2 private HWC2::ComposerCallback @@ -275,7 +272,7 @@ private: */ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - virtual status_t dump(int fd, const Vector& args) { return priorityDump(fd, args); } + virtual status_t dump(int fd, const Vector& args); /* ------------------------------------------------------------------------ * ISurfaceComposer interface @@ -595,13 +592,6 @@ private: /* ------------------------------------------------------------------------ * Debugging & dumpsys */ -public: - status_t dumpCritical(int fd, const Vector& /*args*/) { - return doDump(fd, Vector()); - } - - status_t dumpAll(int fd, const Vector& args) { return doDump(fd, args); } -private: void listLayersLocked(const Vector& args, size_t& index, String8& result) const; void dumpStatsLocked(const Vector& args, size_t& index, String8& result) const; void clearStatsLocked(const Vector& args, size_t& index, String8& result); @@ -626,7 +616,6 @@ private: bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; } - status_t doDump(int fd, const Vector& args); #ifdef USE_HWC2 /* ------------------------------------------------------------------------ diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index 6a24891b08..e50f3ce1f9 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -105,8 +105,7 @@ int main(int, char**) { // publish surface flinger sp sm(defaultServiceManager()); - sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false, - IServiceManager::DUMP_PRIORITY_CRITICAL); + sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false); // publish GpuService sp gpuservice = new GpuService(); diff --git a/services/utils/Android.bp b/services/utils/Android.bp index 6132956eeb..467349153f 100644 --- a/services/utils/Android.bp +++ b/services/utils/Android.bp @@ -20,6 +20,7 @@ cc_library_static { cflags: [ "-Wall", + "-Wno-unused-parameter", "-Werror", ], diff --git a/services/utils/PriorityDumper.cpp b/services/utils/PriorityDumper.cpp index 9851188b46..555cf03bf0 100644 --- a/services/utils/PriorityDumper.cpp +++ b/services/utils/PriorityDumper.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "include/serviceutils/PriorityDumper.h" +#include "include/PriorityDumper.h" namespace android { @@ -25,35 +25,22 @@ static void getStrippedArgs(Vector& dest, const Vector& sour } } -status_t PriorityDumper::dumpAll(int fd, const Vector& args) { - status_t status; - status = dumpCritical(fd, args); - if (status != OK) return status; - status = dumpHigh(fd, args); - if (status != OK) return status; - status = dumpNormal(fd, args); - if (status != OK) return status; - return status; -} - -status_t PriorityDumper::priorityDump(int fd, const Vector& args) { - status_t status; +void priorityDump(PriorityDumper& dumper, int fd, const Vector& args) { if (args.size() >= 2 && args[0] == PRIORITY_ARG) { String16 priority = args[1]; Vector strippedArgs; getStrippedArgs(strippedArgs, args, 2); if (priority == PRIORITY_ARG_CRITICAL) { - status = dumpCritical(fd, strippedArgs); + dumper.dumpCritical(fd, strippedArgs); } else if (priority == PRIORITY_ARG_HIGH) { - status = dumpHigh(fd, strippedArgs); + dumper.dumpHigh(fd, strippedArgs); } else if (priority == PRIORITY_ARG_NORMAL) { - status = dumpNormal(fd, strippedArgs); + dumper.dumpNormal(fd, strippedArgs); } else { - status = dumpAll(fd, args); + dumper.dump(fd, args); } } else { - status = dumpAll(fd, args); + dumper.dump(fd, args); } - return status; } -} // namespace android +} // namespace android \ No newline at end of file diff --git a/services/utils/include/PriorityDumper.h b/services/utils/include/PriorityDumper.h new file mode 100644 index 0000000000..23e900d90e --- /dev/null +++ b/services/utils/include/PriorityDumper.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_UTILS_PRIORITYDUMP_H +#define ANDROID_UTILS_PRIORITYDUMP_H + +#include +#include + +namespace android { + +constexpr const char16_t PRIORITY_ARG[] = u"--dump-priority"; +constexpr const char16_t PRIORITY_ARG_CRITICAL[] = u"CRITICAL"; +constexpr const char16_t PRIORITY_ARG_HIGH[] = u"HIGH"; +constexpr const char16_t PRIORITY_ARG_NORMAL[] = u"NORMAL"; + +// Helper class to split dumps into various priority buckets. +class PriorityDumper { +public: + // Dumps CRITICAL priority sections. + virtual void dumpCritical(int fd, const Vector& args) {} + + // Dumps HIGH priority sections. + virtual void dumpHigh(int fd, const Vector& args) {} + + // Dumps normal priority sections. + virtual void dumpNormal(int fd, const Vector& args) {} + + // Dumps all sections. + // This method is called when priorityDump is called without priority + // arguments. By default, it calls all three dump methods. + virtual void dump(int fd, const Vector& args) { + dumpCritical(fd, args); + dumpHigh(fd, args); + dumpNormal(fd, args); + } + virtual ~PriorityDumper() = default; +}; + +// Parses the argument list checking if the first argument is --dump_priority and +// the second argument is the priority type (HIGH, CRITICAL or NORMAL). If the +// arguments are found, they are stripped and the appropriate PriorityDumper +// method is called. +// If --dump_priority argument is not passed, all supported sections are dumped. +void priorityDump(PriorityDumper& dumper, int fd, const Vector& args); + +}; // namespace android + +#endif // ANDROID_UTILS_PRIORITYDUMP_H diff --git a/services/utils/include/serviceutils/PriorityDumper.h b/services/utils/include/serviceutils/PriorityDumper.h deleted file mode 100644 index 0319242404..0000000000 --- a/services/utils/include/serviceutils/PriorityDumper.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_UTILS_PRIORITYDUMPER_H -#define ANDROID_UTILS_PRIORITYDUMPER_H - -#include -#include -#include - -namespace android { - -constexpr const char16_t PRIORITY_ARG[] = u"--dump-priority"; -constexpr const char16_t PRIORITY_ARG_CRITICAL[] = u"CRITICAL"; -constexpr const char16_t PRIORITY_ARG_HIGH[] = u"HIGH"; -constexpr const char16_t PRIORITY_ARG_NORMAL[] = u"NORMAL"; - -// Helper class to split dumps into various priority buckets. -class PriorityDumper { -public: - // Parses the argument list checking if the first argument is --dump_priority and - // the second argument is the priority type (HIGH, CRITICAL or NORMAL). If the - // arguments are found, they are stripped and the appropriate PriorityDumper - // method is called. - // If --dump_priority argument is not passed, all supported sections are dumped. - status_t priorityDump(int fd, const Vector& args); - - // Dumps CRITICAL priority sections. - virtual status_t dumpCritical(int /*fd*/, const Vector& /*args*/) { return OK; } - - // Dumps HIGH priority sections. - virtual status_t dumpHigh(int /*fd*/, const Vector& /*args*/) { return OK; } - - // Dumps normal priority sections. - virtual status_t dumpNormal(int /*fd*/, const Vector& /*args*/) { return OK; } - - // Dumps all sections. - // This method is called when priorityDump is called without priority - // arguments. By default, it calls all three dump methods. - virtual status_t dumpAll(int fd, const Vector& args); - virtual ~PriorityDumper() = default; -}; - -} // namespace android - -#endif // ANDROID_UTILS_PRIORITYDUMPER_H diff --git a/services/utils/tests/Android.bp b/services/utils/tests/Android.bp index 15829fa12b..5a9dc0a333 100644 --- a/services/utils/tests/Android.bp +++ b/services/utils/tests/Android.bp @@ -21,6 +21,9 @@ cc_test { shared_libs: [ "libutils", ], + cflags: [ + "-Wno-unused-parameter", + ], static_libs = [ "libgmock", "libserviceutils" diff --git a/services/utils/tests/PriorityDumper_test.cpp b/services/utils/tests/PriorityDumper_test.cpp index 79e7340878..c5a121e3fc 100644 --- a/services/utils/tests/PriorityDumper_test.cpp +++ b/services/utils/tests/PriorityDumper_test.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "serviceutils/PriorityDumper.h" +#include "PriorityDumper.h" #include @@ -32,17 +32,17 @@ using ::testing::Test; class PriorityDumperMock : public PriorityDumper { public: - MOCK_METHOD2(dumpCritical, status_t(int, const Vector&)); - MOCK_METHOD2(dumpHigh, status_t(int, const Vector&)); - MOCK_METHOD2(dumpNormal, status_t(int, const Vector&)); - MOCK_METHOD2(dumpAll, status_t(int, const Vector&)); + MOCK_METHOD2(dumpCritical, void(int, const Vector&)); + MOCK_METHOD2(dumpHigh, void(int, const Vector&)); + MOCK_METHOD2(dumpNormal, void(int, const Vector&)); + MOCK_METHOD2(dump, void(int, const Vector&)); }; class DumpAllMock : public PriorityDumper { public: - MOCK_METHOD2(dumpCritical, status_t(int, const Vector&)); - MOCK_METHOD2(dumpHigh, status_t(int, const Vector&)); - MOCK_METHOD2(dumpNormal, status_t(int, const Vector&)); + MOCK_METHOD2(dumpCritical, void(int, const Vector&)); + MOCK_METHOD2(dumpHigh, void(int, const Vector&)); + MOCK_METHOD2(dumpNormal, void(int, const Vector&)); }; class PriorityDumperTest : public Test { @@ -61,15 +61,15 @@ static void addAll(Vector& av, const std::vector& v) { TEST_F(PriorityDumperTest, noArgsPassed) { Vector args; - EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); - dumper_.priorityDump(fd, args); + EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); + priorityDump(dumper_, fd, args); } TEST_F(PriorityDumperTest, noPriorityArgsPassed) { Vector args; addAll(args, {"bunch", "of", "args"}); - EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); - dumper_.priorityDump(fd, args); + EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); + priorityDump(dumper_, fd, args); } TEST_F(PriorityDumperTest, priorityArgsOnly) { @@ -77,7 +77,8 @@ TEST_F(PriorityDumperTest, priorityArgsOnly) { addAll(args, {"--dump-priority", "CRITICAL"}); Vector strippedArgs; EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs))); - dumper_.priorityDump(fd, args); + + priorityDump(dumper_, fd, args); } TEST_F(PriorityDumperTest, dumpCritical) { @@ -87,7 +88,7 @@ TEST_F(PriorityDumperTest, dumpCritical) { addAll(strippedArgs, {"args", "left", "behind"}); EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs))); - dumper_.priorityDump(fd, args); + priorityDump(dumper_, fd, args); } TEST_F(PriorityDumperTest, dumpHigh) { @@ -97,7 +98,7 @@ TEST_F(PriorityDumperTest, dumpHigh) { addAll(strippedArgs, {"args", "left", "behind"}); EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs))); - dumper_.priorityDump(fd, args); + priorityDump(dumper_, fd, args); } TEST_F(PriorityDumperTest, dumpNormal) { @@ -107,7 +108,7 @@ TEST_F(PriorityDumperTest, dumpNormal) { addAll(strippedArgs, {"args", "left", "behind"}); EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs))); - dumper_.priorityDump(fd, args); + priorityDump(dumper_, fd, args); } TEST_F(PriorityDumperTest, dumpAll) { @@ -118,21 +119,21 @@ TEST_F(PriorityDumperTest, dumpAll) { EXPECT_CALL(dumpAlldumper_, dumpHigh(fd, ElementsAreArray(args))); EXPECT_CALL(dumpAlldumper_, dumpNormal(fd, ElementsAreArray(args))); - dumpAlldumper_.priorityDump(fd, args); + priorityDump(dumpAlldumper_, fd, args); } TEST_F(PriorityDumperTest, priorityArgWithPriorityMissing) { Vector args; addAll(args, {"--dump-priority"}); - EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); + EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); - dumper_.priorityDump(fd, args); + priorityDump(dumper_, fd, args); } TEST_F(PriorityDumperTest, priorityArgWithInvalidPriority) { Vector args; addAll(args, {"--dump-priority", "REALLY_HIGH"}); - EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); + EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); - dumper_.priorityDump(fd, args); + priorityDump(dumper_, fd, args); } \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 357988777218502ed68a56a0c8b247ba64b74721 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 6 Oct 2017 16:00:36 -0700 Subject: Support priority based dumpsys in surface flinger Call dump with no args when called with CRITICAL priority. Register service with support for critical priority dumps. BUG: 31774394 Test: lunch mini_emulator_x86-userdebug && make -j56 Test: adb bugreport ~/tmp.zip Test: adb shell dumpsys --priority CRITICAL Test: mmm -j32 frameworks/native/services/utils && \ adb sync data && adb shell /data/nativetest/prioritydumper_test/prioritydumper_test && \ adb shell /data/nativetest64/prioritydumper_test/prioritydumper_test && \ printf "\n\n#### ALL TESTS PASSED ####\n" Change-Id: Iec35ef8026d4d9346c83bab203bed8524c28bf89 --- services/surfaceflinger/Android.bp | 2 + services/surfaceflinger/Android.mk | 8 ++- services/surfaceflinger/SurfaceFlinger.cpp | 3 +- services/surfaceflinger/SurfaceFlinger.h | 13 ++++- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 2 +- services/surfaceflinger/main_surfaceflinger.cpp | 3 +- services/utils/Android.bp | 1 - services/utils/PriorityDumper.cpp | 29 +++++++--- services/utils/include/PriorityDumper.h | 62 ---------------------- .../utils/include/serviceutils/PriorityDumper.h | 59 ++++++++++++++++++++ services/utils/tests/Android.bp | 3 -- services/utils/tests/PriorityDumper_test.cpp | 43 ++++++++------- 12 files changed, 125 insertions(+), 103 deletions(-) delete mode 100644 services/utils/include/PriorityDumper.h create mode 100644 services/utils/include/serviceutils/PriorityDumper.h (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 4775e4ef54..64a2a509ab 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -1,6 +1,8 @@ cc_library_static { name: "libsurfaceflingerincludes", export_include_dirs: ["."], + static_libs = ["libserviceutils"], + export_static_lib_headers = ["libserviceutils"], } subdirs = ["tests/fakehwc"] \ No newline at end of file diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 1f4427a11a..390263ff2e 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -67,7 +67,10 @@ LOCAL_STATIC_LIBRARIES := \ libtrace_proto \ libvkjson \ libvr_manager \ - libvrflinger + libvrflinger \ + libserviceutils + +LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libserviceutils LOCAL_SHARED_LIBRARIES := \ android.frameworks.vr.composer@1.0 \ @@ -145,7 +148,8 @@ LOCAL_SHARED_LIBRARIES := \ libdl LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain -LOCAL_STATIC_LIBRARIES := libtrace_proto +LOCAL_STATIC_LIBRARIES := libtrace_proto \ + libserviceutils LOCAL_MODULE := surfaceflinger diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f04cb884c3..5982422658 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3459,8 +3459,7 @@ void SurfaceFlinger::setPowerMode(const sp& display, int mode) { // --------------------------------------------------------------------------- -status_t SurfaceFlinger::dump(int fd, const Vector& args) -{ +status_t SurfaceFlinger::doDump(int fd, const Vector& args) { String8 result; IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e87d35f912..47ad7b93f2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -47,6 +47,8 @@ #include +#include + #include #include @@ -105,6 +107,7 @@ enum { }; class SurfaceFlinger : public BnSurfaceComposer, + public PriorityDumper, private IBinder::DeathRecipient, #ifdef USE_HWC2 private HWC2::ComposerCallback @@ -272,7 +275,7 @@ private: */ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - virtual status_t dump(int fd, const Vector& args); + virtual status_t dump(int fd, const Vector& args) { return priorityDump(fd, args); } /* ------------------------------------------------------------------------ * ISurfaceComposer interface @@ -592,6 +595,13 @@ private: /* ------------------------------------------------------------------------ * Debugging & dumpsys */ +public: + status_t dumpCritical(int fd, const Vector& /*args*/) { + return doDump(fd, Vector()); + } + + status_t dumpAll(int fd, const Vector& args) { return doDump(fd, args); } +private: void listLayersLocked(const Vector& args, size_t& index, String8& result) const; void dumpStatsLocked(const Vector& args, size_t& index, String8& result) const; void clearStatsLocked(const Vector& args, size_t& index, String8& result); @@ -616,6 +626,7 @@ private: bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; } + status_t doDump(int fd, const Vector& args); #ifdef USE_HWC2 /* ------------------------------------------------------------------------ diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index b0021383ff..b718ec806c 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -3005,7 +3005,7 @@ void SurfaceFlinger::setPowerMode(const sp& display, int mode) { // --------------------------------------------------------------------------- -status_t SurfaceFlinger::dump(int fd, const Vector& args) +status_t SurfaceFlinger::doDump(int fd, const Vector& args) { String8 result; diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index e50f3ce1f9..6a24891b08 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -105,7 +105,8 @@ int main(int, char**) { // publish surface flinger sp sm(defaultServiceManager()); - sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false); + sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false, + IServiceManager::DUMP_PRIORITY_CRITICAL); // publish GpuService sp gpuservice = new GpuService(); diff --git a/services/utils/Android.bp b/services/utils/Android.bp index 467349153f..6132956eeb 100644 --- a/services/utils/Android.bp +++ b/services/utils/Android.bp @@ -20,7 +20,6 @@ cc_library_static { cflags: [ "-Wall", - "-Wno-unused-parameter", "-Werror", ], diff --git a/services/utils/PriorityDumper.cpp b/services/utils/PriorityDumper.cpp index 555cf03bf0..9851188b46 100644 --- a/services/utils/PriorityDumper.cpp +++ b/services/utils/PriorityDumper.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "include/PriorityDumper.h" +#include "include/serviceutils/PriorityDumper.h" namespace android { @@ -25,22 +25,35 @@ static void getStrippedArgs(Vector& dest, const Vector& sour } } -void priorityDump(PriorityDumper& dumper, int fd, const Vector& args) { +status_t PriorityDumper::dumpAll(int fd, const Vector& args) { + status_t status; + status = dumpCritical(fd, args); + if (status != OK) return status; + status = dumpHigh(fd, args); + if (status != OK) return status; + status = dumpNormal(fd, args); + if (status != OK) return status; + return status; +} + +status_t PriorityDumper::priorityDump(int fd, const Vector& args) { + status_t status; if (args.size() >= 2 && args[0] == PRIORITY_ARG) { String16 priority = args[1]; Vector strippedArgs; getStrippedArgs(strippedArgs, args, 2); if (priority == PRIORITY_ARG_CRITICAL) { - dumper.dumpCritical(fd, strippedArgs); + status = dumpCritical(fd, strippedArgs); } else if (priority == PRIORITY_ARG_HIGH) { - dumper.dumpHigh(fd, strippedArgs); + status = dumpHigh(fd, strippedArgs); } else if (priority == PRIORITY_ARG_NORMAL) { - dumper.dumpNormal(fd, strippedArgs); + status = dumpNormal(fd, strippedArgs); } else { - dumper.dump(fd, args); + status = dumpAll(fd, args); } } else { - dumper.dump(fd, args); + status = dumpAll(fd, args); } + return status; } -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/utils/include/PriorityDumper.h b/services/utils/include/PriorityDumper.h deleted file mode 100644 index 23e900d90e..0000000000 --- a/services/utils/include/PriorityDumper.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_UTILS_PRIORITYDUMP_H -#define ANDROID_UTILS_PRIORITYDUMP_H - -#include -#include - -namespace android { - -constexpr const char16_t PRIORITY_ARG[] = u"--dump-priority"; -constexpr const char16_t PRIORITY_ARG_CRITICAL[] = u"CRITICAL"; -constexpr const char16_t PRIORITY_ARG_HIGH[] = u"HIGH"; -constexpr const char16_t PRIORITY_ARG_NORMAL[] = u"NORMAL"; - -// Helper class to split dumps into various priority buckets. -class PriorityDumper { -public: - // Dumps CRITICAL priority sections. - virtual void dumpCritical(int fd, const Vector& args) {} - - // Dumps HIGH priority sections. - virtual void dumpHigh(int fd, const Vector& args) {} - - // Dumps normal priority sections. - virtual void dumpNormal(int fd, const Vector& args) {} - - // Dumps all sections. - // This method is called when priorityDump is called without priority - // arguments. By default, it calls all three dump methods. - virtual void dump(int fd, const Vector& args) { - dumpCritical(fd, args); - dumpHigh(fd, args); - dumpNormal(fd, args); - } - virtual ~PriorityDumper() = default; -}; - -// Parses the argument list checking if the first argument is --dump_priority and -// the second argument is the priority type (HIGH, CRITICAL or NORMAL). If the -// arguments are found, they are stripped and the appropriate PriorityDumper -// method is called. -// If --dump_priority argument is not passed, all supported sections are dumped. -void priorityDump(PriorityDumper& dumper, int fd, const Vector& args); - -}; // namespace android - -#endif // ANDROID_UTILS_PRIORITYDUMP_H diff --git a/services/utils/include/serviceutils/PriorityDumper.h b/services/utils/include/serviceutils/PriorityDumper.h new file mode 100644 index 0000000000..0319242404 --- /dev/null +++ b/services/utils/include/serviceutils/PriorityDumper.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_UTILS_PRIORITYDUMPER_H +#define ANDROID_UTILS_PRIORITYDUMPER_H + +#include +#include +#include + +namespace android { + +constexpr const char16_t PRIORITY_ARG[] = u"--dump-priority"; +constexpr const char16_t PRIORITY_ARG_CRITICAL[] = u"CRITICAL"; +constexpr const char16_t PRIORITY_ARG_HIGH[] = u"HIGH"; +constexpr const char16_t PRIORITY_ARG_NORMAL[] = u"NORMAL"; + +// Helper class to split dumps into various priority buckets. +class PriorityDumper { +public: + // Parses the argument list checking if the first argument is --dump_priority and + // the second argument is the priority type (HIGH, CRITICAL or NORMAL). If the + // arguments are found, they are stripped and the appropriate PriorityDumper + // method is called. + // If --dump_priority argument is not passed, all supported sections are dumped. + status_t priorityDump(int fd, const Vector& args); + + // Dumps CRITICAL priority sections. + virtual status_t dumpCritical(int /*fd*/, const Vector& /*args*/) { return OK; } + + // Dumps HIGH priority sections. + virtual status_t dumpHigh(int /*fd*/, const Vector& /*args*/) { return OK; } + + // Dumps normal priority sections. + virtual status_t dumpNormal(int /*fd*/, const Vector& /*args*/) { return OK; } + + // Dumps all sections. + // This method is called when priorityDump is called without priority + // arguments. By default, it calls all three dump methods. + virtual status_t dumpAll(int fd, const Vector& args); + virtual ~PriorityDumper() = default; +}; + +} // namespace android + +#endif // ANDROID_UTILS_PRIORITYDUMPER_H diff --git a/services/utils/tests/Android.bp b/services/utils/tests/Android.bp index 5a9dc0a333..15829fa12b 100644 --- a/services/utils/tests/Android.bp +++ b/services/utils/tests/Android.bp @@ -21,9 +21,6 @@ cc_test { shared_libs: [ "libutils", ], - cflags: [ - "-Wno-unused-parameter", - ], static_libs = [ "libgmock", "libserviceutils" diff --git a/services/utils/tests/PriorityDumper_test.cpp b/services/utils/tests/PriorityDumper_test.cpp index c5a121e3fc..79e7340878 100644 --- a/services/utils/tests/PriorityDumper_test.cpp +++ b/services/utils/tests/PriorityDumper_test.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "PriorityDumper.h" +#include "serviceutils/PriorityDumper.h" #include @@ -32,17 +32,17 @@ using ::testing::Test; class PriorityDumperMock : public PriorityDumper { public: - MOCK_METHOD2(dumpCritical, void(int, const Vector&)); - MOCK_METHOD2(dumpHigh, void(int, const Vector&)); - MOCK_METHOD2(dumpNormal, void(int, const Vector&)); - MOCK_METHOD2(dump, void(int, const Vector&)); + MOCK_METHOD2(dumpCritical, status_t(int, const Vector&)); + MOCK_METHOD2(dumpHigh, status_t(int, const Vector&)); + MOCK_METHOD2(dumpNormal, status_t(int, const Vector&)); + MOCK_METHOD2(dumpAll, status_t(int, const Vector&)); }; class DumpAllMock : public PriorityDumper { public: - MOCK_METHOD2(dumpCritical, void(int, const Vector&)); - MOCK_METHOD2(dumpHigh, void(int, const Vector&)); - MOCK_METHOD2(dumpNormal, void(int, const Vector&)); + MOCK_METHOD2(dumpCritical, status_t(int, const Vector&)); + MOCK_METHOD2(dumpHigh, status_t(int, const Vector&)); + MOCK_METHOD2(dumpNormal, status_t(int, const Vector&)); }; class PriorityDumperTest : public Test { @@ -61,15 +61,15 @@ static void addAll(Vector& av, const std::vector& v) { TEST_F(PriorityDumperTest, noArgsPassed) { Vector args; - EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); - priorityDump(dumper_, fd, args); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, noPriorityArgsPassed) { Vector args; addAll(args, {"bunch", "of", "args"}); - EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); - priorityDump(dumper_, fd, args); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, priorityArgsOnly) { @@ -77,8 +77,7 @@ TEST_F(PriorityDumperTest, priorityArgsOnly) { addAll(args, {"--dump-priority", "CRITICAL"}); Vector strippedArgs; EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs))); - - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, dumpCritical) { @@ -88,7 +87,7 @@ TEST_F(PriorityDumperTest, dumpCritical) { addAll(strippedArgs, {"args", "left", "behind"}); EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs))); - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, dumpHigh) { @@ -98,7 +97,7 @@ TEST_F(PriorityDumperTest, dumpHigh) { addAll(strippedArgs, {"args", "left", "behind"}); EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs))); - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, dumpNormal) { @@ -108,7 +107,7 @@ TEST_F(PriorityDumperTest, dumpNormal) { addAll(strippedArgs, {"args", "left", "behind"}); EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs))); - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, dumpAll) { @@ -119,21 +118,21 @@ TEST_F(PriorityDumperTest, dumpAll) { EXPECT_CALL(dumpAlldumper_, dumpHigh(fd, ElementsAreArray(args))); EXPECT_CALL(dumpAlldumper_, dumpNormal(fd, ElementsAreArray(args))); - priorityDump(dumpAlldumper_, fd, args); + dumpAlldumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, priorityArgWithPriorityMissing) { Vector args; addAll(args, {"--dump-priority"}); - EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, priorityArgWithInvalidPriority) { Vector args; addAll(args, {"--dump-priority", "REALLY_HIGH"}); - EXPECT_CALL(dumper_, dump(fd, ElementsAreArray(args))); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); - priorityDump(dumper_, fd, args); + dumper_.priorityDump(fd, args); } \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 1d04428c3cff3503212ec3e76775ca5ba20abc18 Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 27 Sep 2017 12:19:28 -0700 Subject: Added protobuf to gather layer info. Use protobuf to gather information about the layers. This change also uses protobuf for the layer dumpsys. Test: Ran dumpsys for layers to confirm the data was correct. Change-Id: Iec474e57a4fb9de1e548440d6a08685505947278 --- include/layerproto | 1 + services/surfaceflinger/Android.bp | 2 +- services/surfaceflinger/Android.mk | 7 +- services/surfaceflinger/Layer.cpp | 77 +++++++ services/surfaceflinger/Layer.h | 5 + services/surfaceflinger/LayerProtoHelper.cpp | 63 ++++++ services/surfaceflinger/LayerProtoHelper.h | 39 ++++ services/surfaceflinger/SurfaceFlinger.cpp | 26 ++- services/surfaceflinger/SurfaceFlinger.h | 5 + services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 26 ++- services/surfaceflinger/layerproto/Android.bp | 35 ++++ .../surfaceflinger/layerproto/LayerProtoParser.cpp | 223 +++++++++++++++++++++ .../include/layerproto/LayerProtoHeader.h | 23 +++ .../include/layerproto/LayerProtoParser.h | 174 ++++++++++++++++ services/surfaceflinger/layerproto/layers.proto | 110 ++++++++++ services/surfaceflinger/tests/fakehwc/Android.bp | 3 +- 16 files changed, 809 insertions(+), 10 deletions(-) create mode 120000 include/layerproto create mode 100644 services/surfaceflinger/LayerProtoHelper.cpp create mode 100644 services/surfaceflinger/LayerProtoHelper.h create mode 100644 services/surfaceflinger/layerproto/Android.bp create mode 100644 services/surfaceflinger/layerproto/LayerProtoParser.cpp create mode 100644 services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h create mode 100644 services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h create mode 100644 services/surfaceflinger/layerproto/layers.proto (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/include/layerproto b/include/layerproto new file mode 120000 index 0000000000..ef21a4eb8e --- /dev/null +++ b/include/layerproto @@ -0,0 +1 @@ +../services/surfaceflinger/layerproto/include/layerproto/ \ No newline at end of file diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 64a2a509ab..bd7f0ea364 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -5,4 +5,4 @@ cc_library_static { export_static_lib_headers = ["libserviceutils"], } -subdirs = ["tests/fakehwc"] \ No newline at end of file +subdirs = ["tests/fakehwc", "layerproto"] \ No newline at end of file diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 390263ff2e..d8152e08cc 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -39,6 +39,7 @@ LOCAL_SRC_FILES := \ RenderEngine/RenderEngine.cpp \ RenderEngine/Texture.cpp \ RenderEngine/GLES20RenderEngine.cpp \ + LayerProtoHelper.cpp \ LOCAL_MODULE := libsurfaceflinger LOCAL_C_INCLUDES := \ @@ -98,7 +99,8 @@ LOCAL_SHARED_LIBRARIES := \ libsync \ libprotobuf-cpp-lite \ libbase \ - android.hardware.power@1.0 + android.hardware.power@1.0 \ + liblayers_proto LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \ android.hardware.graphics.allocator@2.0 \ @@ -145,7 +147,8 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libui \ libgui \ - libdl + libdl \ + liblayers_proto LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain LOCAL_STATIC_LIBRARIES := libtrace_proto \ diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 956f7f6c02..27739ce074 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -56,6 +56,7 @@ #include "RenderEngine/RenderEngine.h" #include +#include "LayerProtoHelper.h" #define DEBUG_RESIZE 0 @@ -2826,6 +2827,82 @@ void Layer::commitChildList() { mDrawingParent = mCurrentParent; } +void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; + const State& state = useDrawing ? mDrawingState : mCurrentState; + + Transform requestedTransform = state.active.transform; + Transform transform = getTransform(); + + layerInfo->set_id(sequence); + layerInfo->set_name(getName().c_str()); + layerInfo->set_type(String8(getTypeId())); + + for (const auto& child : children) { + layerInfo->add_children(child->sequence); + } + + for (const wp& weakRelative : state.zOrderRelatives) { + sp strongRelative = weakRelative.promote(); + if (strongRelative != nullptr) { + layerInfo->add_relatives(strongRelative->sequence); + } + } + + LayerProtoHelper::writeToProto(state.activeTransparentRegion, + layerInfo->mutable_transparent_region()); + LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region()); + LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region()); + + layerInfo->set_layer_stack(getLayerStack()); + layerInfo->set_z(state.z); + + PositionProto* position = layerInfo->mutable_position(); + position->set_x(transform.tx()); + position->set_y(transform.ty()); + + PositionProto* requestedPosition = layerInfo->mutable_requested_position(); + requestedPosition->set_x(requestedTransform.tx()); + requestedPosition->set_y(requestedTransform.ty()); + + SizeProto* size = layerInfo->mutable_size(); + size->set_w(state.active.w); + size->set_h(state.active.h); + + LayerProtoHelper::writeToProto(state.crop, layerInfo->mutable_crop()); + LayerProtoHelper::writeToProto(state.finalCrop, layerInfo->mutable_final_crop()); + + layerInfo->set_is_opaque(isOpaque(state)); + layerInfo->set_invalidate(contentDirty); + layerInfo->set_dataspace(dataspaceDetails(getDataSpace())); + layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat())); + LayerProtoHelper::writeToProto(getColor(), layerInfo->mutable_color()); + LayerProtoHelper::writeToProto(state.color, layerInfo->mutable_requested_color()); + layerInfo->set_flags(state.flags); + + LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform()); + LayerProtoHelper::writeToProto(requestedTransform, layerInfo->mutable_requested_transform()); + + auto parent = getParent(); + if (parent != nullptr) { + layerInfo->set_parent(parent->sequence); + } + + auto zOrderRelativeOf = state.zOrderRelativeOf.promote(); + if (zOrderRelativeOf != nullptr) { + layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence); + } + + auto activeBuffer = getActiveBuffer(); + if (activeBuffer != nullptr) { + LayerProtoHelper::writeToProto(activeBuffer, layerInfo->mutable_active_buffer()); + } + + layerInfo->set_queued_frames(getQueuedFrameCount()); + layerInfo->set_refresh_pending(isBufferLatched()); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 47924ae877..06c4863ce2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -49,9 +49,12 @@ #include "DisplayHardware/HWComposerBufferCache.h" #include "RenderEngine/Mesh.h" #include "RenderEngine/Texture.h" +#include #include +using namespace android::surfaceflinger; + namespace android { // --------------------------------------------------------------------------- @@ -303,6 +306,8 @@ public: */ virtual bool isFixedSize() const; + void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); + protected: /* * onDraw - draws the surface. diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp new file mode 100644 index 0000000000..6a33148d27 --- /dev/null +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LayerProtoHelper.h" + +namespace android { +namespace surfaceflinger { +void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) { + Region::const_iterator head = region.begin(); + Region::const_iterator const tail = region.end(); + uint64_t address = reinterpret_cast(®ion); + regionProto->set_id(address); + while (head != tail) { + RectProto* rectProto = regionProto->add_rect(); + writeToProto(*head, rectProto); + head++; + } +} + +void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) { + rectProto->set_left(rect.left); + rectProto->set_top(rect.top); + rectProto->set_bottom(rect.bottom); + rectProto->set_right(rect.right); +} + +void LayerProtoHelper::writeToProto(const half4 color, ColorProto* colorProto) { + colorProto->set_r(color.r); + colorProto->set_g(color.g); + colorProto->set_b(color.b); + colorProto->set_a(color.a); +} + +void LayerProtoHelper::writeToProto(const Transform& transform, TransformProto* transformProto) { + transformProto->set_dsdx(transform[0][0]); + transformProto->set_dtdx(transform[0][1]); + transformProto->set_dsdy(transform[1][0]); + transformProto->set_dtdy(transform[1][1]); +} + +void LayerProtoHelper::writeToProto(const sp& buffer, + ActiveBufferProto* activeBufferProto) { + activeBufferProto->set_width(buffer->getWidth()); + activeBufferProto->set_height(buffer->getHeight()); + activeBufferProto->set_stride(buffer->getStride()); + activeBufferProto->set_format(buffer->format); +} + +} // namespace surfaceflinger +} // namespace android diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h new file mode 100644 index 0000000000..45a0b5d173 --- /dev/null +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include + +#include + +namespace android { +namespace surfaceflinger { +class LayerProtoHelper { +public: + static void writeToProto(const Rect& rect, RectProto* rectProto); + static void writeToProto(const Region& region, RegionProto* regionProto); + static void writeToProto(const half4 color, ColorProto* colorProto); + static void writeToProto(const Transform& transform, TransformProto* transformProto); + static void writeToProto(const sp& buffer, ActiveBufferProto* activeBufferProto); +}; + +} // namespace surfaceflinger +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5982422658..4a982524b5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -90,6 +90,8 @@ #include #include +#include + #define DISPLAY_COUNT 1 /* @@ -3532,6 +3534,13 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args) { dumpWideColorInfo(result); dumpAll = false; } + + if ((index < numArgs) && (args[index] == String16("--proto"))) { + index++; + LayersProto layersProto = dumpProtoInfo(); + result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); + dumpAll = false; + } } if (dumpAll) { @@ -3727,6 +3736,16 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { result.append("\n"); } +LayersProto SurfaceFlinger::dumpProtoInfo() const { + LayersProto layersProto; + mCurrentState.traverseInZOrder([&](Layer* layer) { + LayerProto* layerProto = layersProto.add_layers(); + layer->writeToProto(layerProto, LayerVector::StateSet::Current); + }); + + return layersProto; +} + void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, String8& result) const { @@ -3791,9 +3810,10 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, colorizer.bold(result); result.appendFormat("Visible layers (count = %zu)\n", mNumLayers); colorizer.reset(result); - mCurrentState.traverseInZOrder([&](Layer* layer) { - result.append(to_string(layer->getLayerDebugInfo()).c_str()); - }); + + LayersProto layersProto = dumpProtoInfo(); + auto layerTree = LayerProtoParser::generateLayerTree(layersProto); + result.append(LayerProtoParser::layersToString(layerTree).c_str()); /* * Dump Display state diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2cba500500..9030124e8d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -78,6 +78,10 @@ #include #include +#include + +using namespace android::surfaceflinger; + namespace android { // --------------------------------------------------------------------------- @@ -622,6 +626,7 @@ private: std::vector&& history); void dumpBufferingStats(String8& result) const; void dumpWideColorInfo(String8& result) const; + LayersProto dumpProtoInfo() const; bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index b718ec806c..ed7641fe99 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -87,6 +87,8 @@ #include #include +#include + #define DISPLAY_COUNT 1 /* @@ -3073,6 +3075,13 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args) dumpFrameEventsLocked(result); dumpAll = false; } + + if ((index < numArgs) && (args[index] == String16("--proto"))) { + index++; + LayersProto layersProto = dumpProtoInfo(); + result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); + dumpAll = false; + } } if (dumpAll) { @@ -3243,6 +3252,16 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { result.append("\n"); } +LayersProto SurfaceFlinger::dumpProtoInfo() const { + LayersProto layersProto; + mCurrentState.traverseInZOrder([&](Layer* layer) { + LayerProto* layerProto = layersProto.add_layers(); + layer->writeToProto(layerProto, LayerVector::StateSet::Current); + }); + + return layersProto; +} + void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, String8& result) const { @@ -3302,9 +3321,10 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, colorizer.bold(result); result.appendFormat("Visible layers (count = %zu)\n", mNumLayers); colorizer.reset(result); - mCurrentState.traverseInZOrder([&](Layer* layer) { - result.append(to_string(layer->getLayerDebugInfo()).c_str()); - }); + + LayersProto layersProto = dumpProtoInfo(); + auto layerTree = LayerProtoParser::generateLayerTree(layersProto); + result.append(LayerProtoParser::layersToString(layerTree).c_str()); /* * Dump Display state diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp new file mode 100644 index 0000000000..4c52bdfaa7 --- /dev/null +++ b/services/surfaceflinger/layerproto/Android.bp @@ -0,0 +1,35 @@ +cc_library_shared { + name: "liblayers_proto", + vendor_available: true, + export_include_dirs: ["include"], + + srcs: [ + "LayerProtoParser.cpp", + "layers.proto", + ], + + shared_libs: [ + "libui", + "libprotobuf-cpp-lite", + "libbase", + ], + + proto: { + export_proto_headers: true, + }, + + cppflags: [ + "-Werror", + "-Wno-unused-parameter", + "-Wno-format", + "-Wno-c++98-compat-pedantic", + "-Wno-float-conversion", + "-Wno-disabled-macro-expansion", + "-Wno-float-equal", + "-Wno-sign-conversion", + "-Wno-padded", + "-Wno-old-style-cast", + "-Wno-undef", + ], + +} \ No newline at end of file diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp new file mode 100644 index 0000000000..65541674f1 --- /dev/null +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace android { +namespace surfaceflinger { +bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) { + uint32_t ls = lhs->layerStack; + uint32_t rs = rhs->layerStack; + if (ls != rs) return ls < rs; + + uint32_t lz = lhs->z; + uint32_t rz = rhs->z; + if (lz != rz) return lz < rz; + + return lhs->id < rhs->id; +} + +std::vector LayerProtoParser::generateLayerTree( + const LayersProto& layersProto) { + auto layerMap = generateMap(layersProto); + + std::vector layers; + std::for_each(layerMap.begin(), layerMap.end(), + [&](const std::pair& ref) { + if (ref.second->parent == nullptr) { + // only save top level layers + layers.push_back(ref.second); + } + }); + + std::sort(layers.begin(), layers.end(), sortLayers); + return layers; +} + +std::unordered_map LayerProtoParser::generateMap( + const LayersProto& layersProto) { + std::unordered_map layerMap; + + for (int i = 0; i < layersProto.layers_size(); i++) { + const LayerProto& layerProto = layersProto.layers(i); + layerMap[layerProto.id()] = generateLayer(layerProto); + } + + for (int i = 0; i < layersProto.layers_size(); i++) { + const LayerProto& layerProto = layersProto.layers(i); + updateChildrenAndRelative(layerProto, layerMap); + } + + return layerMap; +} + +LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layerProto) { + Layer* layer = new Layer(); + layer->id = layerProto.id(); + layer->name = layerProto.name(); + layer->type = layerProto.type(); + layer->transparentRegion = generateRegion(layerProto.transparent_region()); + layer->visibleRegion = generateRegion(layerProto.visible_region()); + layer->damageRegion = generateRegion(layerProto.damage_region()); + layer->layerStack = layerProto.layer_stack(); + layer->z = layerProto.z(); + layer->position = {layerProto.position().x(), layerProto.position().y()}; + layer->requestedPosition = {layerProto.requested_position().x(), + layerProto.requested_position().y()}; + layer->size = {layerProto.size().w(), layerProto.size().h()}; + layer->crop = generateRect(layerProto.crop()); + layer->finalCrop = generateRect(layerProto.final_crop()); + layer->isOpaque = layerProto.is_opaque(); + layer->invalidate = layerProto.invalidate(); + layer->dataspace = layerProto.dataspace(); + layer->pixelFormat = layerProto.pixel_format(); + layer->color = {layerProto.color().r(), layerProto.color().g(), layerProto.color().b(), + layerProto.color().a()}; + layer->requestedColor = {layerProto.requested_color().r(), layerProto.requested_color().g(), + layerProto.requested_color().b(), layerProto.requested_color().a()}; + layer->flags = layerProto.flags(); + layer->transform = generateTransform(layerProto.transform()); + layer->requestedTransform = generateTransform(layerProto.requested_transform()); + layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer()); + layer->queuedFrames = layerProto.queued_frames(); + layer->refreshPending = layerProto.refresh_pending(); + + return layer; +} + +LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) { + LayerProtoParser::Region region; + region.id = regionProto.id(); + for (int i = 0; i < regionProto.rect_size(); i++) { + const RectProto& rectProto = regionProto.rect(i); + region.rects.push_back(generateRect(rectProto)); + } + + return region; +} + +LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto) { + LayerProtoParser::Rect rect; + rect.left = rectProto.left(); + rect.top = rectProto.top(); + rect.right = rectProto.right(); + rect.bottom = rectProto.bottom(); + + return rect; +} + +LayerProtoParser::Transform LayerProtoParser::generateTransform( + const TransformProto& transformProto) { + LayerProtoParser::Transform transform; + transform.dsdx = transformProto.dsdx(); + transform.dtdx = transformProto.dtdx(); + transform.dsdy = transformProto.dsdy(); + transform.dtdy = transformProto.dtdy(); + + return transform; +} + +LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer( + const ActiveBufferProto& activeBufferProto) { + LayerProtoParser::ActiveBuffer activeBuffer; + activeBuffer.width = activeBufferProto.width(); + activeBuffer.height = activeBufferProto.height(); + activeBuffer.stride = activeBufferProto.stride(); + activeBuffer.format = activeBufferProto.format(); + + return activeBuffer; +} + +void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto, + std::unordered_map& layerMap) { + auto currLayer = layerMap[layerProto.id()]; + + for (int i = 0; i < layerProto.children_size(); i++) { + if (layerMap.count(layerProto.children(i)) > 0) { + auto childLayer = layerMap[layerProto.children(i)]; + currLayer->children.push_back(childLayer); + } + } + + for (int i = 0; i < layerProto.relatives_size(); i++) { + if (layerMap.count(layerProto.relatives(i)) > 0) { + auto relativeLayer = layerMap[layerProto.relatives(i)]; + currLayer->relatives.push_back(relativeLayer); + } + } + + if (layerProto.has_parent()) { + if (layerMap.count(layerProto.parent()) > 0) { + auto parentLayer = layerMap[layerProto.parent()]; + currLayer->parent = parentLayer; + } + } + + if (layerProto.has_z_order_relative_of()) { + if (layerMap.count(layerProto.z_order_relative_of()) > 0) { + auto relativeLayer = layerMap[layerProto.z_order_relative_of()]; + currLayer->zOrderRelativeOf = relativeLayer; + } + } +} + +std::string LayerProtoParser::layersToString( + const std::vector layers) { + std::string result; + for (const LayerProtoParser::Layer* layer : layers) { + if (layer->zOrderRelativeOf != nullptr) { + continue; + } + result.append(layerToString(layer).c_str()); + } + + return result; +} + +std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer) { + std::string result; + + std::vector traverse(layer->relatives); + for (const LayerProtoParser::Layer* child : layer->children) { + if (child->zOrderRelativeOf != nullptr) { + continue; + } + + traverse.push_back(child); + } + + std::sort(traverse.begin(), traverse.end(), sortLayers); + + size_t i = 0; + for (; i < traverse.size(); i++) { + const auto& relative = traverse[i]; + if (relative->z >= 0) { + break; + } + result.append(layerToString(relative).c_str()); + } + result.append(layer->to_string().c_str()); + result.append("\n"); + for (; i < traverse.size(); i++) { + const auto& relative = traverse[i]; + result.append(layerToString(relative).c_str()); + } + + return result; +} + +} // namespace surfaceflinger +} // namespace android diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h new file mode 100644 index 0000000000..054d4f2cbc --- /dev/null +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2007 The Android Open Source Projectlayerproto/LayerProtoHeader.h + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// pragma is used here to disable the warnings emitted from the protobuf +// headers. By adding #pragma before including layer.pb.h, it supresses +// protobuf warnings, but allows the rest of the files to continuing using +// the current flags. +// This file should be included instead of directly including layer.b.h +#pragma GCC system_header +#include diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h new file mode 100644 index 0000000000..7b94cefbc8 --- /dev/null +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include +#include +#include +#include + +using android::base::StringAppendF; +using android::base::StringPrintf; + +namespace android { +namespace surfaceflinger { + +class LayerProtoParser { +public: + class ActiveBuffer { + public: + uint32_t width; + uint32_t height; + uint32_t stride; + int32_t format; + + std::string to_string() const { + return StringPrintf("[%4ux%4u:%4u,%s]", width, height, stride, + decodePixelFormat(format).c_str()); + } + }; + + class Transform { + public: + float dsdx; + float dtdx; + float dsdy; + float dtdy; + + std::string to_string() const { + return StringPrintf("[%.2f, %.2f][%.2f, %.2f]", static_cast(dsdx), + static_cast(dtdx), static_cast(dsdy), + static_cast(dtdy)); + } + }; + + class Rect { + public: + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; + + std::string to_string() const { + return StringPrintf("[%3d, %3d, %3d, %3d]", left, top, right, bottom); + } + }; + + class Region { + public: + uint64_t id; + std::vector rects; + + std::string to_string(const char* what) const { + std::string result = + StringPrintf(" Region %s (this=%lx count=%d)\n", what, + static_cast(id), static_cast(rects.size())); + + for (auto& rect : rects) { + StringAppendF(&result, " %s\n", rect.to_string().c_str()); + } + + return result; + } + }; + + class Layer { + public: + int32_t id; + std::string name; + std::vector children; + std::vector relatives; + std::string type; + LayerProtoParser::Region transparentRegion; + LayerProtoParser::Region visibleRegion; + LayerProtoParser::Region damageRegion; + uint32_t layerStack; + int32_t z; + float2 position; + float2 requestedPosition; + int2 size; + LayerProtoParser::Rect crop; + LayerProtoParser::Rect finalCrop; + bool isOpaque; + bool invalidate; + std::string dataspace; + std::string pixelFormat; + half4 color; + half4 requestedColor; + uint32_t flags; + Transform transform; + Transform requestedTransform; + Layer* parent = 0; + Layer* zOrderRelativeOf = 0; + LayerProtoParser::ActiveBuffer activeBuffer; + int32_t queuedFrames; + bool refreshPending; + + std::string to_string() const { + std::string result; + StringAppendF(&result, "+ %s (%s)\n", type.c_str(), name.c_str()); + result.append(transparentRegion.to_string("TransparentRegion").c_str()); + result.append(visibleRegion.to_string("VisibleRegion").c_str()); + result.append(damageRegion.to_string("SurfaceDamageRegion").c_str()); + + StringAppendF(&result, " layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ", + layerStack, z, static_cast(position.x), + static_cast(position.y), size.x, size.y); + + StringAppendF(&result, "crop=%s, finalCrop=%s, ", crop.to_string().c_str(), + finalCrop.to_string().c_str()); + StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate); + StringAppendF(&result, "dataspace=%s, ", dataspace.c_str()); + StringAppendF(&result, "pixelformat=%s, ", pixelFormat.c_str()); + StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ", + static_cast(color.r), static_cast(color.g), + static_cast(color.b), static_cast(color.a), flags); + StringAppendF(&result, "tr=%s", transform.to_string().c_str()); + result.append("\n"); + StringAppendF(&result, " parent=%s\n", + parent == nullptr ? "none" : parent->name.c_str()); + StringAppendF(&result, " zOrderRelativeOf=%s\n", + zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str()); + StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str()); + StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames, + refreshPending); + + return result; + } + }; + + static std::vector generateLayerTree(const LayersProto& layersProto); + static std::string layersToString(const std::vector layers); + +private: + static std::unordered_map generateMap(const LayersProto& layersProto); + static LayerProtoParser::Layer* generateLayer(const LayerProto& layerProto); + static LayerProtoParser::Region generateRegion(const RegionProto& regionProto); + static LayerProtoParser::Rect generateRect(const RectProto& rectProto); + static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto); + static LayerProtoParser::ActiveBuffer generateActiveBuffer( + const ActiveBufferProto& activeBufferProto); + static void updateChildrenAndRelative(const LayerProto& layerProto, + std::unordered_map& layerMap); + + static std::string layerToString(const LayerProtoParser::Layer* layer); +}; + +} // namespace surfaceflinger +} // namespace android diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto new file mode 100644 index 0000000000..d27dc9b2ea --- /dev/null +++ b/services/surfaceflinger/layerproto/layers.proto @@ -0,0 +1,110 @@ +// Definitions for SurfaceFlinger layers. + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; +package android.surfaceflinger; + +// Contains a list of all layers. +message LayersProto { + repeated LayerProto layers = 1; +} + +// Information about each layer. +message LayerProto { + // unique id per layer. + optional int32 id = 1; + // unique name per layer. + optional string name = 2; + // list of children this layer may have. May be empty. + repeated int32 children = 3; + // list of layers that are z order relative to this layer. + repeated int32 relatives = 4; + // The type of layer, ex Color, Layer + optional string type = 5; + optional RegionProto transparent_region = 6; + optional RegionProto visible_region = 7; + optional RegionProto damage_region = 8; + optional uint32 layer_stack = 9; + // The layer's z order. Can be z order in layer stack, relative to parent, + // or relative to another layer specified in zOrderRelative. + optional int32 z = 10; + // The layer's position on the display. + optional PositionProto position = 11; + // The layer's requested position. + optional PositionProto requested_position = 12; + // The layer's size. + optional SizeProto size = 13; + // The layer's crop in it's own bounds. + optional RectProto crop = 14; + // The layer's crop in it's parent's bounds. + optional RectProto final_crop = 15; + optional bool is_opaque = 16; + optional bool invalidate = 17; + optional string dataspace = 18; + optional string pixel_format = 19; + // The layer's actual color. + optional ColorProto color = 20; + // The layer's requested color. + optional ColorProto requested_color = 21; + // Can be any combination of + // hidden = 0x01 + // opaque = 0x02, + // secure = 0x80, + optional uint32 flags = 22; + // The layer's actual transform + optional TransformProto transform = 23; + // The layer's requested transform. + optional TransformProto requested_transform = 24; + // The parent layer. This value can be null if there is no parent. + optional int32 parent = 25 [default = -1]; + // The layer that this layer has a z order relative to. This value can be null. + optional int32 z_order_relative_of = 26 [default = -1]; + // This value can be null if there's nothing to draw. + optional ActiveBufferProto active_buffer = 27; + // The number of frames available. + optional int32 queued_frames = 28; + optional bool refresh_pending = 29; +} + +message PositionProto { + optional float x = 1; + optional float y = 2; +} + +message SizeProto { + optional int32 w = 1; + optional int32 h = 2; +} + +message TransformProto { + optional float dsdx = 1; + optional float dtdx = 2; + optional float dsdy = 3; + optional float dtdy = 4; +} + +message RegionProto { + optional uint64 id = 1; + repeated RectProto rect = 2; +} + +message RectProto { + optional int32 left = 1; + optional int32 top = 2; + optional int32 right = 3; + optional int32 bottom = 4; +} + +message ActiveBufferProto { + optional uint32 width = 1; + optional uint32 height = 2; + optional uint32 stride = 3; + optional int32 format = 4; +} + +message ColorProto { + optional float r = 1; + optional float g = 2; + optional float b = 3; + optional float a = 4; +} \ No newline at end of file diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 94f3f2561a..212b9e7ebb 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -22,7 +22,8 @@ cc_test { "libsync", "libfmq", "libbase", - "libhidltransport" + "libhidltransport", + "liblayers_proto" ], static_libs: [ "libhwcomposer-client", -- cgit v1.2.3-59-g8ed1b From 6a40853e06f5274d84b0fc66e349a36510d1497f Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 24 Oct 2017 09:11:27 -0700 Subject: Add proto dump flag to services (1/2) Adds new PROTO flag which requests services to dump sections in proto format. Modifies dumpsys to take in proto argument and pass on proto flags to services which support proto dumps. Modify PriorityDumper helper class to parse proto arguments and set asProto flags. Bug: 67716082 Test: mmm -j56 frameworks/native/cmds/dumpsys && \ mmm -j56 frameworks/native/services/utils && \ adb sync data && \ adb shell /data/nativetest/dumpsys_test/dumpsys_test && \ adb shell /data/nativetest64/dumpsys_test/dumpsys_test && \ adb shell /data/nativetest/prioritydumper_test/prioritydumper_test && \ adb shell /data/nativetest64/prioritydumper_test/prioritydumper_test && \ printf "\n\n#### ALL TESTS PASSED ####\n" Change-Id: I42c2a6a8876efbf9a7d792d68572499b16985147 --- cmds/dumpsys/dumpsys.cpp | 42 +++++--- cmds/dumpsys/tests/Android.bp | 1 + cmds/dumpsys/tests/dumpsys_test.cpp | 88 +++++++++++++--- libs/binder/include/binder/BinderService.h | 11 +- libs/binder/include/binder/IServiceManager.h | 15 +-- services/surfaceflinger/SurfaceFlinger.cpp | 8 +- services/surfaceflinger/SurfaceFlinger.h | 11 +- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 9 +- services/surfaceflinger/main_surfaceflinger.cpp | 2 +- services/utils/PriorityDumper.cpp | 69 ++++++++---- .../utils/include/serviceutils/PriorityDumper.h | 39 ++++--- services/utils/tests/PriorityDumper_test.cpp | 117 +++++++++++++++++---- 12 files changed, 308 insertions(+), 104 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp index 239a2d5e69..c36ab0872a 100644 --- a/cmds/dumpsys/dumpsys.cpp +++ b/cmds/dumpsys/dumpsys.cpp @@ -62,6 +62,8 @@ static void usage() { " --help: shows this help\n" " -l: only list services, do not dump them\n" " -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n" + " --proto: filter services that support dumping data in proto format. Dumps" + " will be in proto format.\n" " --priority LEVEL: filter services based on specified priority\n" " LEVEL must be one of CRITICAL | HIGH | NORMAL\n" " --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n" @@ -77,17 +79,17 @@ static bool IsSkipped(const Vector& skipped, const String16& service) return false; } -static bool ConvertPriorityTypeToBitmask(String16& type, int& bitmask) { - if (type == PRIORITY_ARG_CRITICAL) { - bitmask = IServiceManager::DUMP_PRIORITY_CRITICAL; +static bool ConvertPriorityTypeToBitmask(const String16& type, int& bitmask) { + if (type == PriorityDumper::PRIORITY_ARG_CRITICAL) { + bitmask = IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL; return true; } - if (type == PRIORITY_ARG_HIGH) { - bitmask = IServiceManager::DUMP_PRIORITY_HIGH; + if (type == PriorityDumper::PRIORITY_ARG_HIGH) { + bitmask = IServiceManager::DUMP_FLAG_PRIORITY_HIGH; return true; } - if (type == PRIORITY_ARG_NORMAL) { - bitmask = IServiceManager::DUMP_PRIORITY_NORMAL; + if (type == PriorityDumper::PRIORITY_ARG_NORMAL) { + bitmask = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL; return true; } return false; @@ -98,11 +100,14 @@ int Dumpsys::main(int argc, char* const argv[]) { Vector args; String16 priorityType; Vector skippedServices; + Vector protoServices; bool showListOnly = false; bool skipServices = false; + bool filterByProto = false; int timeoutArg = 10; - int dumpPriority = IServiceManager::DUMP_PRIORITY_ALL; + int dumpPriorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL; static struct option longOptions[] = {{"priority", required_argument, 0, 0}, + {"proto", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, {"help", no_argument, 0, 0}, {0, 0, 0, 0}}; @@ -124,12 +129,14 @@ int Dumpsys::main(int argc, char* const argv[]) { case 0: if (!strcmp(longOptions[optionIndex].name, "skip")) { skipServices = true; + } else if (!strcmp(longOptions[optionIndex].name, "proto")) { + filterByProto = true; } else if (!strcmp(longOptions[optionIndex].name, "help")) { usage(); return 0; } else if (!strcmp(longOptions[optionIndex].name, "priority")) { priorityType = String16(String8(optarg)); - if (!ConvertPriorityTypeToBitmask(priorityType, dumpPriority)) { + if (!ConvertPriorityTypeToBitmask(priorityType, dumpPriorityFlags)) { fprintf(stderr, "\n"); usage(); return -1; @@ -179,10 +186,19 @@ int Dumpsys::main(int argc, char* const argv[]) { if (services.empty() || showListOnly) { // gets all services - services = sm_->listServices(dumpPriority); + services = sm_->listServices(dumpPriorityFlags); services.sort(sort_func); - if (dumpPriority != IServiceManager::DUMP_PRIORITY_ALL) { - args.insertAt(String16(PRIORITY_ARG), 0); + if (filterByProto) { + protoServices = sm_->listServices(IServiceManager::DUMP_FLAG_PROTO); + protoServices.sort(sort_func); + Vector intersection; + std::set_intersection(services.begin(), services.end(), protoServices.begin(), + protoServices.end(), std::back_inserter(intersection)); + services = std::move(intersection); + args.insertAt(String16(PriorityDumper::PROTO_ARG), 0); + } + if (dumpPriorityFlags != IServiceManager::DUMP_FLAG_PRIORITY_ALL) { + args.insertAt(String16(PriorityDumper::PRIORITY_ARG), 0); args.insertAt(priorityType, 1); } else { args.add(String16("-a")); @@ -230,7 +246,7 @@ int Dumpsys::main(int argc, char* const argv[]) { if (N > 1) { aout << "------------------------------------------------------------" "-------------------" << endl; - if (dumpPriority == IServiceManager::DUMP_PRIORITY_ALL) { + if (dumpPriorityFlags == IServiceManager::DUMP_FLAG_PRIORITY_ALL) { aout << "DUMP OF SERVICE " << service_name << ":" << endl; } else { aout << "DUMP OF SERVICE " << priorityType << " " << service_name << ":" << endl; diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp index 39fcb80631..e182b9d287 100644 --- a/cmds/dumpsys/tests/Android.bp +++ b/cmds/dumpsys/tests/Android.bp @@ -15,6 +15,7 @@ cc_test { static_libs: [ "libdumpsys", "libgmock", + "libserviceutils", ], clang: true, diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index 9fe45729af..18a4da9739 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -131,16 +132,16 @@ class DumpsysTest : public Test { for (auto& service : services) { services16.add(String16(service.c_str())); } - EXPECT_CALL(sm_, listServices(IServiceManager::DUMP_PRIORITY_ALL)) + EXPECT_CALL(sm_, listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL)) .WillRepeatedly(Return(services16)); } - void ExpectListServicesWithPriority(std::vector services, int dumpPriority) { + void ExpectListServicesWithPriority(std::vector services, int dumpFlags) { Vector services16; for (auto& service : services) { services16.add(String16(service.c_str())); } - EXPECT_CALL(sm_, listServices(dumpPriority)).WillRepeatedly(Return(services16)); + EXPECT_CALL(sm_, listServices(dumpFlags)).WillRepeatedly(Return(services16)); } sp ExpectCheckService(const char* name, bool running = true) { @@ -210,6 +211,13 @@ class DumpsysTest : public Test { EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n" + dump)); } + void AssertDumpedWithPriority(const std::string& service, const std::string& dump, + const char16_t* priorityType) { + std::string priority = String8(priorityType).c_str(); + EXPECT_THAT(stdout_, + HasSubstr("DUMP OF SERVICE " + priority + " " + service + ":\n" + dump)); + } + void AssertNotDumped(const std::string& dump) { EXPECT_THAT(stdout_, Not(HasSubstr(dump))); } @@ -250,7 +258,7 @@ TEST_F(DumpsysTest, ListRunningServices) { // Tests 'dumpsys -l --priority HIGH' TEST_F(DumpsysTest, ListAllServicesWithPriority) { - ExpectListServicesWithPriority({"Locksmith", "Valet"}, IServiceManager::DUMP_PRIORITY_HIGH); + ExpectListServicesWithPriority({"Locksmith", "Valet"}, IServiceManager::DUMP_FLAG_PRIORITY_HIGH); ExpectCheckService("Locksmith"); ExpectCheckService("Valet"); @@ -261,13 +269,26 @@ TEST_F(DumpsysTest, ListAllServicesWithPriority) { // Tests 'dumpsys -l --priority HIGH' with and empty list TEST_F(DumpsysTest, ListEmptyServicesWithPriority) { - ExpectListServicesWithPriority({}, IServiceManager::DUMP_PRIORITY_HIGH); + ExpectListServicesWithPriority({}, IServiceManager::DUMP_FLAG_PRIORITY_HIGH); CallMain({"-l", "--priority", "HIGH"}); AssertRunningServices({}); } +// Tests 'dumpsys -l --proto' +TEST_F(DumpsysTest, ListAllServicesWithProto) { + ExpectListServicesWithPriority({"Locksmith", "Valet", "Car"}, + IServiceManager::DUMP_FLAG_PRIORITY_ALL); + ExpectListServicesWithPriority({"Valet", "Car"}, IServiceManager::DUMP_FLAG_PROTO); + ExpectCheckService("Car"); + ExpectCheckService("Valet"); + + CallMain({"-l", "--proto"}); + + AssertRunningServices({"Car", "Valet"}); +} + // Tests 'dumpsys service_name' on a service is running TEST_F(DumpsysTest, DumpRunningService) { ExpectDump("Valet", "Here's your car"); @@ -336,7 +357,7 @@ TEST_F(DumpsysTest, DumpWithSkip) { // Tests 'dumpsys --skip skipped3 skipped5 --priority CRITICAL', which should skip these services TEST_F(DumpsysTest, DumpWithSkipAndPriority) { ExpectListServicesWithPriority({"running1", "stopped2", "skipped3", "running4", "skipped5"}, - IServiceManager::DUMP_PRIORITY_CRITICAL); + IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); ExpectDump("running1", "dump1"); ExpectCheckService("stopped2", false); ExpectDump("skipped3", "dump3"); @@ -346,8 +367,8 @@ TEST_F(DumpsysTest, DumpWithSkipAndPriority) { CallMain({"--priority", "CRITICAL", "--skip", "skipped3", "skipped5"}); AssertRunningServices({"running1", "running4", "skipped3 (skipped)", "skipped5 (skipped)"}); - AssertDumped("running1", "dump1"); - AssertDumped("running4", "dump4"); + AssertDumpedWithPriority("running1", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL); + AssertDumpedWithPriority("running4", "dump4", PriorityDumper::PRIORITY_ARG_CRITICAL); AssertStopped("stopped2"); AssertNotDumped("dump3"); AssertNotDumped("dump5"); @@ -356,41 +377,74 @@ TEST_F(DumpsysTest, DumpWithSkipAndPriority) { // Tests 'dumpsys --priority CRITICAL' TEST_F(DumpsysTest, DumpWithPriorityCritical) { ExpectListServicesWithPriority({"runningcritical1", "runningcritical2"}, - IServiceManager::DUMP_PRIORITY_CRITICAL); + IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); ExpectDump("runningcritical1", "dump1"); ExpectDump("runningcritical2", "dump2"); CallMain({"--priority", "CRITICAL"}); AssertRunningServices({"runningcritical1", "runningcritical2"}); - AssertDumped("runningcritical1", "dump1"); - AssertDumped("runningcritical2", "dump2"); + AssertDumpedWithPriority("runningcritical1", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL); + AssertDumpedWithPriority("runningcritical2", "dump2", PriorityDumper::PRIORITY_ARG_CRITICAL); } // Tests 'dumpsys --priority HIGH' TEST_F(DumpsysTest, DumpWithPriorityHigh) { ExpectListServicesWithPriority({"runninghigh1", "runninghigh2"}, - IServiceManager::DUMP_PRIORITY_HIGH); + IServiceManager::DUMP_FLAG_PRIORITY_HIGH); ExpectDump("runninghigh1", "dump1"); ExpectDump("runninghigh2", "dump2"); CallMain({"--priority", "HIGH"}); AssertRunningServices({"runninghigh1", "runninghigh2"}); - AssertDumped("runninghigh1", "dump1"); - AssertDumped("runninghigh2", "dump2"); + AssertDumpedWithPriority("runninghigh1", "dump1", PriorityDumper::PRIORITY_ARG_HIGH); + AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH); } // Tests 'dumpsys --priority NORMAL' TEST_F(DumpsysTest, DumpWithPriorityNormal) { ExpectListServicesWithPriority({"runningnormal1", "runningnormal2"}, - IServiceManager::DUMP_PRIORITY_NORMAL); + IServiceManager::DUMP_FLAG_PRIORITY_NORMAL); ExpectDump("runningnormal1", "dump1"); ExpectDump("runningnormal2", "dump2"); CallMain({"--priority", "NORMAL"}); AssertRunningServices({"runningnormal1", "runningnormal2"}); - AssertDumped("runningnormal1", "dump1"); - AssertDumped("runningnormal2", "dump2"); + AssertDumpedWithPriority("runningnormal1", "dump1", PriorityDumper::PRIORITY_ARG_NORMAL); + AssertDumpedWithPriority("runningnormal2", "dump2", PriorityDumper::PRIORITY_ARG_NORMAL); +} + +// Tests 'dumpsys --proto' +TEST_F(DumpsysTest, DumpWithProto) { + ExpectListServicesWithPriority({"run8", "run1", "run2", "run5"}, + IServiceManager::DUMP_FLAG_PRIORITY_ALL); + ExpectListServicesWithPriority({"run3", "run2", "run4", "run8"}, + IServiceManager::DUMP_FLAG_PROTO); + ExpectDump("run2", "dump1"); + ExpectDump("run8", "dump2"); + + CallMain({"--proto"}); + + AssertRunningServices({"run2", "run8"}); + AssertDumped("run2", "dump1"); + AssertDumped("run8", "dump2"); +} + +// Tests 'dumpsys --priority HIGH --proto' +TEST_F(DumpsysTest, DumpWithPriorityHighAndProto) { + ExpectListServicesWithPriority({"runninghigh1", "runninghigh2"}, + IServiceManager::DUMP_FLAG_PRIORITY_HIGH); + ExpectListServicesWithPriority({"runninghigh1", "runninghigh2", "runninghigh3"}, + IServiceManager::DUMP_FLAG_PROTO); + + ExpectDump("runninghigh1", "dump1"); + ExpectDump("runninghigh2", "dump2"); + + CallMain({"--priority", "HIGH", "--proto"}); + + AssertRunningServices({"runninghigh1", "runninghigh2"}); + AssertDumpedWithPriority("runninghigh1", "dump1", PriorityDumper::PRIORITY_ARG_HIGH); + AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH); } diff --git a/libs/binder/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h index 4e6906750b..4ce82a122c 100644 --- a/libs/binder/include/binder/BinderService.h +++ b/libs/binder/include/binder/BinderService.h @@ -35,15 +35,16 @@ class BinderService { public: static status_t publish(bool allowIsolated = false, - int dumpPriority = IServiceManager::DUMP_PRIORITY_NORMAL) { + int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL) { sp sm(defaultServiceManager()); return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated, - dumpPriority); + dumpFlags); } - static void publishAndJoinThreadPool(bool allowIsolated = false, - int dumpPriority = IServiceManager::DUMP_PRIORITY_NORMAL) { - publish(allowIsolated, dumpPriority); + static void publishAndJoinThreadPool( + bool allowIsolated = false, + int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL) { + publish(allowIsolated, dumpFlags); joinThreadPool(); } diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index 78b03bde14..19e841a347 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -34,11 +34,12 @@ public: /* * Must match values in IServiceManager.java */ - static const int DUMP_PRIORITY_CRITICAL = 1 << 0; - static const int DUMP_PRIORITY_HIGH = 1 << 1; - static const int DUMP_PRIORITY_NORMAL = 1 << 2; - static const int DUMP_PRIORITY_ALL = - DUMP_PRIORITY_CRITICAL | DUMP_PRIORITY_HIGH | DUMP_PRIORITY_NORMAL; + static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0; + static const int DUMP_FLAG_PRIORITY_HIGH = 1 << 1; + static const int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2; + static const int DUMP_FLAG_PRIORITY_ALL = + DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL; + static const int DUMP_FLAG_PROTO = 1 << 3; /** * Retrieve an existing service, blocking for a few seconds @@ -56,12 +57,12 @@ public: */ virtual status_t addService(const String16& name, const sp& service, bool allowIsolated = false, - int dumpsysPriority = DUMP_PRIORITY_NORMAL) = 0; + int dumpsysFlags = DUMP_FLAG_PRIORITY_NORMAL) = 0; /** * Return list of all existing services. */ - virtual Vector listServices(int dumpsysPriority = DUMP_PRIORITY_ALL) = 0; + virtual Vector listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0; enum { GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5982422658..63ccba72c7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3459,12 +3459,18 @@ void SurfaceFlinger::setPowerMode(const sp& display, int mode) { // --------------------------------------------------------------------------- -status_t SurfaceFlinger::doDump(int fd, const Vector& args) { +status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asProto) { String8 result; IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); + + if (asProto) { + // Return early as SurfaceFlinger does not support dumping sections in proto format + return OK; + } + if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) { result.appendFormat("Permission Denial: " diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2cba500500..0fc6a7edde 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -596,11 +596,14 @@ private: * Debugging & dumpsys */ public: - status_t dumpCritical(int fd, const Vector& /*args*/) { - return doDump(fd, Vector()); + status_t dumpCritical(int fd, const Vector& /*args*/, bool asProto) { + return doDump(fd, Vector(), asProto); + } + + status_t dumpAll(int fd, const Vector& args, bool asProto) { + return doDump(fd, args, asProto); } - status_t dumpAll(int fd, const Vector& args) { return doDump(fd, args); } private: void listLayersLocked(const Vector& args, size_t& index, String8& result) const; void dumpStatsLocked(const Vector& args, size_t& index, String8& result) const; @@ -626,7 +629,7 @@ private: bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; } - status_t doDump(int fd, const Vector& args); + status_t doDump(int fd, const Vector& args, bool asProto); #ifdef USE_HWC2 /* ------------------------------------------------------------------------ diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index b718ec806c..81bda02d80 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -3005,13 +3005,18 @@ void SurfaceFlinger::setPowerMode(const sp& display, int mode) { // --------------------------------------------------------------------------- -status_t SurfaceFlinger::doDump(int fd, const Vector& args) -{ +status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asProto) { String8 result; IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); + + if (asProto) { + // Return early as SurfaceFlinger does not support dumping sections in proto format + return OK; + } + if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) { result.appendFormat("Permission Denial: " diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index 6a24891b08..2a924ae1c7 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -106,7 +106,7 @@ int main(int, char**) { // publish surface flinger sp sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false, - IServiceManager::DUMP_PRIORITY_CRITICAL); + IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); // publish GpuService sp gpuservice = new GpuService(); diff --git a/services/utils/PriorityDumper.cpp b/services/utils/PriorityDumper.cpp index 9851188b46..967dee5d29 100644 --- a/services/utils/PriorityDumper.cpp +++ b/services/utils/PriorityDumper.cpp @@ -18,41 +18,68 @@ namespace android { -static void getStrippedArgs(Vector& dest, const Vector& source, - std::size_t numArgsToStrip) { - for (auto it = source.begin() + numArgsToStrip; it != source.end(); it++) { - dest.add(*it); +const char16_t PriorityDumper::PROTO_ARG[] = u"--proto"; +const char16_t PriorityDumper::PRIORITY_ARG[] = u"--dump-priority"; +const char16_t PriorityDumper::PRIORITY_ARG_CRITICAL[] = u"CRITICAL"; +const char16_t PriorityDumper::PRIORITY_ARG_HIGH[] = u"HIGH"; +const char16_t PriorityDumper::PRIORITY_ARG_NORMAL[] = u"NORMAL"; + +enum class PriorityType { INVALID, CRITICAL, HIGH, NORMAL }; + +static PriorityType getPriorityType(const String16& arg) { + if (arg == PriorityDumper::PRIORITY_ARG_CRITICAL) { + return PriorityType::CRITICAL; + } else if (arg == PriorityDumper::PRIORITY_ARG_HIGH) { + return PriorityType::HIGH; + } else if (arg == PriorityDumper::PRIORITY_ARG_NORMAL) { + return PriorityType::NORMAL; } + return PriorityType::INVALID; } -status_t PriorityDumper::dumpAll(int fd, const Vector& args) { +status_t PriorityDumper::dumpAll(int fd, const Vector& args, bool asProto) { status_t status; - status = dumpCritical(fd, args); + status = dumpCritical(fd, args, asProto); if (status != OK) return status; - status = dumpHigh(fd, args); + status = dumpHigh(fd, args, asProto); if (status != OK) return status; - status = dumpNormal(fd, args); + status = dumpNormal(fd, args, asProto); if (status != OK) return status; return status; } status_t PriorityDumper::priorityDump(int fd, const Vector& args) { status_t status; - if (args.size() >= 2 && args[0] == PRIORITY_ARG) { - String16 priority = args[1]; - Vector strippedArgs; - getStrippedArgs(strippedArgs, args, 2); - if (priority == PRIORITY_ARG_CRITICAL) { - status = dumpCritical(fd, strippedArgs); - } else if (priority == PRIORITY_ARG_HIGH) { - status = dumpHigh(fd, strippedArgs); - } else if (priority == PRIORITY_ARG_NORMAL) { - status = dumpNormal(fd, strippedArgs); + bool asProto = false; + PriorityType priority = PriorityType::INVALID; + + Vector strippedArgs; + for (uint32_t argIndex = 0; argIndex < args.size(); argIndex++) { + if (args[argIndex] == PROTO_ARG) { + asProto = true; + } else if (args[argIndex] == PRIORITY_ARG) { + if (argIndex + 1 < args.size()) { + argIndex++; + priority = getPriorityType(args[argIndex]); + } } else { - status = dumpAll(fd, args); + strippedArgs.add(args[argIndex]); } - } else { - status = dumpAll(fd, args); + } + + switch (priority) { + case PriorityType::CRITICAL: + status = dumpCritical(fd, strippedArgs, asProto); + break; + case PriorityType::HIGH: + status = dumpHigh(fd, strippedArgs, asProto); + break; + case PriorityType::NORMAL: + status = dumpNormal(fd, strippedArgs, asProto); + break; + default: + status = dumpAll(fd, strippedArgs, asProto); + break; } return status; } diff --git a/services/utils/include/serviceutils/PriorityDumper.h b/services/utils/include/serviceutils/PriorityDumper.h index 0319242404..d01a102497 100644 --- a/services/utils/include/serviceutils/PriorityDumper.h +++ b/services/utils/include/serviceutils/PriorityDumper.h @@ -23,34 +23,43 @@ namespace android { -constexpr const char16_t PRIORITY_ARG[] = u"--dump-priority"; -constexpr const char16_t PRIORITY_ARG_CRITICAL[] = u"CRITICAL"; -constexpr const char16_t PRIORITY_ARG_HIGH[] = u"HIGH"; -constexpr const char16_t PRIORITY_ARG_NORMAL[] = u"NORMAL"; - -// Helper class to split dumps into various priority buckets. +// Helper class to parse common arguments responsible for splitting dumps into +// various priority buckets and changing the output format of the dump. class PriorityDumper { public: - // Parses the argument list checking if the first argument is --dump_priority and - // the second argument is the priority type (HIGH, CRITICAL or NORMAL). If the - // arguments are found, they are stripped and the appropriate PriorityDumper - // method is called. - // If --dump_priority argument is not passed, all supported sections are dumped. + static const char16_t PRIORITY_ARG[]; + static const char16_t PRIORITY_ARG_CRITICAL[]; + static const char16_t PRIORITY_ARG_HIGH[]; + static const char16_t PRIORITY_ARG_NORMAL[]; + static const char16_t PROTO_ARG[]; + + // Parses the argument list searching for --dump_priority with a priority type + // (HIGH, CRITICAL or NORMAL) and --proto. Matching arguments are stripped. + // If a valid priority type is found, the associated PriorityDumper + // method is called otherwise all supported sections are dumped. + // If --proto is found, the dumpAsProto flag is set to dump sections in proto + // format. status_t priorityDump(int fd, const Vector& args); // Dumps CRITICAL priority sections. - virtual status_t dumpCritical(int /*fd*/, const Vector& /*args*/) { return OK; } + virtual status_t dumpCritical(int /*fd*/, const Vector& /*args*/, bool /*asProto*/) { + return OK; + } // Dumps HIGH priority sections. - virtual status_t dumpHigh(int /*fd*/, const Vector& /*args*/) { return OK; } + virtual status_t dumpHigh(int /*fd*/, const Vector& /*args*/, bool /*asProto*/) { + return OK; + } // Dumps normal priority sections. - virtual status_t dumpNormal(int /*fd*/, const Vector& /*args*/) { return OK; } + virtual status_t dumpNormal(int /*fd*/, const Vector& /*args*/, bool /*asProto*/) { + return OK; + } // Dumps all sections. // This method is called when priorityDump is called without priority // arguments. By default, it calls all three dump methods. - virtual status_t dumpAll(int fd, const Vector& args); + virtual status_t dumpAll(int fd, const Vector& args, bool asProto); virtual ~PriorityDumper() = default; }; diff --git a/services/utils/tests/PriorityDumper_test.cpp b/services/utils/tests/PriorityDumper_test.cpp index 79e7340878..90cc6de790 100644 --- a/services/utils/tests/PriorityDumper_test.cpp +++ b/services/utils/tests/PriorityDumper_test.cpp @@ -32,17 +32,17 @@ using ::testing::Test; class PriorityDumperMock : public PriorityDumper { public: - MOCK_METHOD2(dumpCritical, status_t(int, const Vector&)); - MOCK_METHOD2(dumpHigh, status_t(int, const Vector&)); - MOCK_METHOD2(dumpNormal, status_t(int, const Vector&)); - MOCK_METHOD2(dumpAll, status_t(int, const Vector&)); + MOCK_METHOD3(dumpCritical, status_t(int, const Vector&, bool)); + MOCK_METHOD3(dumpHigh, status_t(int, const Vector&, bool)); + MOCK_METHOD3(dumpNormal, status_t(int, const Vector&, bool)); + MOCK_METHOD3(dumpAll, status_t(int, const Vector&, bool)); }; class DumpAllMock : public PriorityDumper { public: - MOCK_METHOD2(dumpCritical, status_t(int, const Vector&)); - MOCK_METHOD2(dumpHigh, status_t(int, const Vector&)); - MOCK_METHOD2(dumpNormal, status_t(int, const Vector&)); + MOCK_METHOD3(dumpCritical, status_t(int, const Vector&, bool)); + MOCK_METHOD3(dumpHigh, status_t(int, const Vector&, bool)); + MOCK_METHOD3(dumpNormal, status_t(int, const Vector&, bool)); }; class PriorityDumperTest : public Test { @@ -61,14 +61,14 @@ static void addAll(Vector& av, const std::vector& v) { TEST_F(PriorityDumperTest, noArgsPassed) { Vector args; - EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args), /*asProto=*/false)); dumper_.priorityDump(fd, args); } TEST_F(PriorityDumperTest, noPriorityArgsPassed) { Vector args; addAll(args, {"bunch", "of", "args"}); - EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args), /*asProto=*/false)); dumper_.priorityDump(fd, args); } @@ -76,7 +76,7 @@ TEST_F(PriorityDumperTest, priorityArgsOnly) { Vector args; addAll(args, {"--dump-priority", "CRITICAL"}); Vector strippedArgs; - EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs))); + EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false)); dumper_.priorityDump(fd, args); } @@ -86,7 +86,17 @@ TEST_F(PriorityDumperTest, dumpCritical) { Vector strippedArgs; addAll(strippedArgs, {"args", "left", "behind"}); - EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs))); + EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false)); + dumper_.priorityDump(fd, args); +} + +TEST_F(PriorityDumperTest, dumpCriticalInMiddle) { + Vector args; + addAll(args, {"args", "left", "--dump-priority", "CRITICAL", "behind"}); + Vector strippedArgs; + addAll(strippedArgs, {"args", "left", "behind"}); + + EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false)); dumper_.priorityDump(fd, args); } @@ -96,7 +106,17 @@ TEST_F(PriorityDumperTest, dumpHigh) { Vector strippedArgs; addAll(strippedArgs, {"args", "left", "behind"}); - EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs))); + EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs), /*asProto=*/false)); + dumper_.priorityDump(fd, args); +} + +TEST_F(PriorityDumperTest, dumpHighInEnd) { + Vector args; + addAll(args, {"args", "left", "behind", "--dump-priority", "HIGH"}); + Vector strippedArgs; + addAll(strippedArgs, {"args", "left", "behind"}); + + EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs), /*asProto=*/false)); dumper_.priorityDump(fd, args); } @@ -106,7 +126,7 @@ TEST_F(PriorityDumperTest, dumpNormal) { Vector strippedArgs; addAll(strippedArgs, {"args", "left", "behind"}); - EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs))); + EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/false)); dumper_.priorityDump(fd, args); } @@ -114,9 +134,9 @@ TEST_F(PriorityDumperTest, dumpAll) { Vector args; addAll(args, {"args", "left", "behind"}); - EXPECT_CALL(dumpAlldumper_, dumpCritical(fd, ElementsAreArray(args))); - EXPECT_CALL(dumpAlldumper_, dumpHigh(fd, ElementsAreArray(args))); - EXPECT_CALL(dumpAlldumper_, dumpNormal(fd, ElementsAreArray(args))); + EXPECT_CALL(dumpAlldumper_, dumpCritical(fd, ElementsAreArray(args), /*asProto=*/false)); + EXPECT_CALL(dumpAlldumper_, dumpHigh(fd, ElementsAreArray(args), /*asProto=*/false)); + EXPECT_CALL(dumpAlldumper_, dumpNormal(fd, ElementsAreArray(args), /*asProto=*/false)); dumpAlldumper_.priorityDump(fd, args); } @@ -124,7 +144,8 @@ TEST_F(PriorityDumperTest, dumpAll) { TEST_F(PriorityDumperTest, priorityArgWithPriorityMissing) { Vector args; addAll(args, {"--dump-priority"}); - EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); + Vector strippedArgs; + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/false)); dumper_.priorityDump(fd, args); } @@ -132,7 +153,67 @@ TEST_F(PriorityDumperTest, priorityArgWithPriorityMissing) { TEST_F(PriorityDumperTest, priorityArgWithInvalidPriority) { Vector args; addAll(args, {"--dump-priority", "REALLY_HIGH"}); - EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args))); + Vector strippedArgs; + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/false)); + + dumper_.priorityDump(fd, args); +} + +TEST_F(PriorityDumperTest, protoArg) { + Vector args; + addAll(args, {"--proto"}); + Vector strippedArgs; + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true)); + + dumper_.priorityDump(fd, args); +} + +TEST_F(PriorityDumperTest, protoArgWithPriorityArgs) { + Vector args; + addAll(args, {"--proto", "args", "--dump-priority", "NORMAL", "left", "behind"}); + Vector strippedArgs; + addAll(strippedArgs, {"args", "left", "behind"}); + EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/true)); + + dumper_.priorityDump(fd, args); +} + +TEST_F(PriorityDumperTest, protoArgWithPriorityArgsInReverseOrder) { + Vector args; + addAll(args, {"--dump-priority", "NORMAL", "--proto", "args", "left", "behind"}); + Vector strippedArgs; + addAll(strippedArgs, {"args", "left", "behind"}); + EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/true)); + + dumper_.priorityDump(fd, args); +} + +TEST_F(PriorityDumperTest, protoArgInMiddle) { + Vector args; + addAll(args, {"--unknown", "args", "--proto", "args", "left", "behind"}); + Vector strippedArgs; + addAll(strippedArgs, {"--unknown", "args", "args", "left", "behind"}); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true)); + + dumper_.priorityDump(fd, args); +} + +TEST_F(PriorityDumperTest, protoArgAtEnd) { + Vector args; + addAll(args, {"--unknown", "args", "args", "left", "behind", "--proto"}); + Vector strippedArgs; + addAll(strippedArgs, {"--unknown", "args", "args", "left", "behind"}); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true)); + + dumper_.priorityDump(fd, args); +} + +TEST_F(PriorityDumperTest, protoArgWithInvalidPriorityType) { + Vector args; + addAll(args, {"--dump-priority", "NOT_SO_HIGH", "--proto", "args", "left", "behind"}); + Vector strippedArgs; + addAll(strippedArgs, {"args", "left", "behind"}); + EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true)); dumper_.priorityDump(fd, args); } \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 54f154a28284eabb52ade2689d4a9f8fa190163b Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 24 Oct 2017 21:40:32 +0100 Subject: Add new color setting On devices that support wide color rendering and color management, add a new setting to disable color management ("saturated" color mode). To disable color management, the framework can set a persistent property. Color management can be also toggled by using a Binder transaction. Finally this change adds a new Binder query so Settings can easily check whether the device supports wide color rendering. Bug: 68159303 Test: manual (adb shell + apps) Change-Id: If74d9b0273bc04f4a3d11e63fe2ec96451fbcc2e --- services/surfaceflinger/SurfaceFlinger.cpp | 42 ++++++++++++++++++++++++------ services/surfaceflinger/SurfaceFlinger.h | 1 + 2 files changed, 35 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c05ac8aaac..bb0e33cb45 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -656,6 +656,12 @@ void SurfaceFlinger::readPersistentProperties() { property_get("persist.sys.sf.color_saturation", value, "1.0"); mSaturation = atof(value); ALOGV("Saturation is set to %.2f", mSaturation); + + property_get("persist.sys.sf.native_mode", value, "0"); + mForceNativeColorMode = atoi(value) == 1; + if (mForceNativeColorMode) { + ALOGV("Forcing native color mode"); + } } void SurfaceFlinger::startBootAnim() { @@ -1235,12 +1241,13 @@ void SurfaceFlinger::createDefaultDisplayDevice() { break; } } + bool useWideColorMode = hasWideColorModes && hasWideColorDisplay && !mForceNativeColorMode; sp hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure, token, fbs, producer, mRenderEngine->getEGLConfig(), - hasWideColorModes && hasWideColorDisplay); + useWideColorMode); mDisplays.add(token, hw); android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; - if (hasWideColorModes && hasWideColorDisplay) { + if (useWideColorMode) { defaultColorMode = HAL_COLOR_MODE_SRGB; } setActiveColorModeInternal(hw, defaultColorMode); @@ -1756,6 +1763,10 @@ mat4 SurfaceFlinger::computeSaturationMatrix() const { // pickColorMode translates a given dataspace into the best available color mode. // Currently only support sRGB and Display-P3. android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const { + if (mForceNativeColorMode) { + return HAL_COLOR_MODE_NATIVE; + } + switch (dataSpace) { // treat Unknown as regular SRGB buffer, since that's what the rest of the // system expects. @@ -2590,8 +2601,10 @@ bool SurfaceFlinger::doComposeSurfaces( ALOGV("hasClientComposition"); #ifdef USE_HWC2 - mRenderEngine->setWideColor(displayDevice->getWideColorSupport()); - mRenderEngine->setColorMode(displayDevice->getActiveColorMode()); + mRenderEngine->setWideColor( + displayDevice->getWideColorSupport() && !mForceNativeColorMode); + mRenderEngine->setColorMode(mForceNativeColorMode ? + HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode()); #endif if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", @@ -3632,6 +3645,7 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { void SurfaceFlinger::dumpWideColorInfo(String8& result) const { result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay); + result.appendFormat("forceNativeColorMode: %d\n", mForceNativeColorMode); // TODO: print out if wide-color mode is active or not @@ -4085,6 +4099,17 @@ status_t SurfaceFlinger::onTransact( repaintEverything(); return NO_ERROR; } + case 1023: { // Set native mode + mForceNativeColorMode = data.readInt32() == 1; + + invalidateHwcGeometry(); + repaintEverything(); + return NO_ERROR; + } + case 1024: { // Is wide color gamut rendering/color management supported? + reply->writeBool(hasWideColorDisplay); + return NO_ERROR; + } } } return err; @@ -4242,8 +4267,9 @@ status_t SurfaceFlinger::captureScreen(const sp& display, WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL); ANativeWindowBuffer* buffer = nullptr; - result = getWindowBuffer(window, reqWidth, reqHeight, hasWideColorDisplay, - getRenderEngine().usesWideColor(), &buffer); + result = getWindowBuffer(window, reqWidth, reqHeight, + hasWideColorDisplay && !mForceNativeColorMode, + getRenderEngine().usesWideColor(), &buffer); if (result != NO_ERROR) { return result; } @@ -4345,8 +4371,8 @@ void SurfaceFlinger::renderScreenImplLocked( } #ifdef USE_HWC2 - engine.setWideColor(hw->getWideColorSupport()); - engine.setColorMode(hw->getActiveColorMode()); + engine.setWideColor(hw->getWideColorSupport() && !mForceNativeColorMode); + engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : hw->getActiveColorMode()); #endif // make sure to clear all GL error flags diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 13a057f2b6..7606e10a62 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -814,6 +814,7 @@ private: #endif float mSaturation = 1.0f; + bool mForceNativeColorMode = false; }; }; // namespace android -- cgit v1.2.3-59-g8ed1b From a14443fac49543abda174f8c3457ab0b60021b01 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 24 Oct 2017 21:40:32 +0100 Subject: Add new color setting On devices that support wide color rendering and color management, add a new setting to disable color management ("saturated" color mode). To disable color management, the framework can set a persistent property. Color management can be also toggled by using a Binder transaction. Finally this change adds a new Binder query so Settings can easily check whether the device supports wide color rendering. Bug: 68159303 Test: manual (adb shell + apps) Change-Id: If74d9b0273bc04f4a3d11e63fe2ec96451fbcc2e (cherry picked from commit 54f154a28284eabb52ade2689d4a9f8fa190163b) --- services/surfaceflinger/SurfaceFlinger.cpp | 42 ++++++++++++++++++++++++------ services/surfaceflinger/SurfaceFlinger.h | 1 + 2 files changed, 35 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8ed6686ebf..8c90c39245 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -645,6 +645,12 @@ void SurfaceFlinger::readPersistentProperties() { property_get("persist.sys.sf.color_saturation", value, "1.0"); mSaturation = atof(value); ALOGV("Saturation is set to %.2f", mSaturation); + + property_get("persist.sys.sf.native_mode", value, "0"); + mForceNativeColorMode = atoi(value) == 1; + if (mForceNativeColorMode) { + ALOGV("Forcing native color mode"); + } } void SurfaceFlinger::startBootAnim() { @@ -1210,12 +1216,13 @@ void SurfaceFlinger::createDefaultDisplayDevice() { break; } } + bool useWideColorMode = hasWideColorModes && hasWideColorDisplay && !mForceNativeColorMode; sp hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure, token, fbs, producer, mRenderEngine->getEGLConfig(), - hasWideColorModes && hasWideColorDisplay); + useWideColorMode); mDisplays.add(token, hw); android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; - if (hasWideColorModes && hasWideColorDisplay) { + if (useWideColorMode) { defaultColorMode = HAL_COLOR_MODE_SRGB; } setActiveColorModeInternal(hw, defaultColorMode); @@ -1731,6 +1738,10 @@ mat4 SurfaceFlinger::computeSaturationMatrix() const { // pickColorMode translates a given dataspace into the best available color mode. // Currently only support sRGB and Display-P3. android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const { + if (mForceNativeColorMode) { + return HAL_COLOR_MODE_NATIVE; + } + switch (dataSpace) { // treat Unknown as regular SRGB buffer, since that's what the rest of the // system expects. @@ -2568,8 +2579,10 @@ bool SurfaceFlinger::doComposeSurfaces( ALOGV("hasClientComposition"); #ifdef USE_HWC2 - mRenderEngine->setWideColor(displayDevice->getWideColorSupport()); - mRenderEngine->setColorMode(displayDevice->getActiveColorMode()); + mRenderEngine->setWideColor( + displayDevice->getWideColorSupport() && !mForceNativeColorMode); + mRenderEngine->setColorMode(mForceNativeColorMode ? + HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode()); #endif if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", @@ -3607,6 +3620,7 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { void SurfaceFlinger::dumpWideColorInfo(String8& result) const { result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay); + result.appendFormat("forceNativeColorMode: %d\n", mForceNativeColorMode); // TODO: print out if wide-color mode is active or not @@ -4059,6 +4073,17 @@ status_t SurfaceFlinger::onTransact( repaintEverything(); return NO_ERROR; } + case 1023: { // Set native mode + mForceNativeColorMode = data.readInt32() == 1; + + invalidateHwcGeometry(); + repaintEverything(); + return NO_ERROR; + } + case 1024: { // Is wide color gamut rendering/color management supported? + reply->writeBool(hasWideColorDisplay); + return NO_ERROR; + } } } return err; @@ -4210,8 +4235,9 @@ status_t SurfaceFlinger::captureScreen(const sp& display, WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL); ANativeWindowBuffer* buffer = nullptr; - result = getWindowBuffer(window, reqWidth, reqHeight, hasWideColorDisplay, - getRenderEngine().usesWideColor(), &buffer); + result = getWindowBuffer(window, reqWidth, reqHeight, + hasWideColorDisplay && !mForceNativeColorMode, + getRenderEngine().usesWideColor(), &buffer); if (result != NO_ERROR) { return result; } @@ -4313,8 +4339,8 @@ void SurfaceFlinger::renderScreenImplLocked( } #ifdef USE_HWC2 - engine.setWideColor(hw->getWideColorSupport()); - engine.setColorMode(hw->getActiveColorMode()); + engine.setWideColor(hw->getWideColorSupport() && !mForceNativeColorMode); + engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : hw->getActiveColorMode()); #endif // make sure to clear all GL error flags diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index acfad46526..e75d9dcdde 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -772,6 +772,7 @@ private: #endif float mSaturation = 1.0f; + bool mForceNativeColorMode = false; }; }; // namespace android -- cgit v1.2.3-59-g8ed1b From 90f669f238cdc750483d0961efc61bbf551ae782 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 5 Oct 2017 14:24:41 -0700 Subject: surfaceflinger: make vsync injection more robust There are more issues than I expected :) - no lock to synchronize enable/disable and injection - Every time injection is diabled and enabled, a new EventThread is created - mCallback might be nullptr - ENABLE_VSYNC_INJECTIONS/INJECT_VSYNC should require special permission - MessageQueue::setEventThread must be called from the main thread - MessageQueue::setEventThread does not handle EventThread switch well Bug: 65483324 Test: manual Change-Id: I7d7b98d1f57afc64af0f2065a9bc7c8ad004ca9f --- services/surfaceflinger/MessageQueue.cpp | 8 ++++++ services/surfaceflinger/SurfaceFlinger.cpp | 42 ++++++++++++++++++------------ 2 files changed, 34 insertions(+), 16 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp index bca3430794..0b1199c2d0 100644 --- a/services/surfaceflinger/MessageQueue.cpp +++ b/services/surfaceflinger/MessageQueue.cpp @@ -91,6 +91,14 @@ void MessageQueue::init(const sp& flinger) void MessageQueue::setEventThread(const sp& eventThread) { + if (mEventThread == eventThread) { + return; + } + + if (mEventTube.getFd() >= 0) { + mLooper->removeFd(mEventTube.getFd()); + } + mEventThread = eventThread; mEvents = eventThread->createEventConnection(); mEvents->stealReceiveChannel(&mEventTube); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 54c040dae9..05c76fce46 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -570,7 +570,9 @@ public: virtual void onInjectSyncEvent(nsecs_t when) { std::lock_guard lock(mCallbackMutex); - mCallback->onVSyncEvent(when); + if (mCallback) { + mCallback->onVSyncEvent(when); + } } virtual void setVSyncEnabled(bool) {} @@ -1066,28 +1068,34 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp& display, } status_t SurfaceFlinger::enableVSyncInjections(bool enable) { - if (enable == mInjectVSyncs) { - return NO_ERROR; - } + sp enableVSyncInjections = new LambdaMessage([&]() { + Mutex::Autolock _l(mStateLock); - if (enable) { - mInjectVSyncs = enable; - ALOGV("VSync Injections enabled"); - if (mVSyncInjector.get() == nullptr) { - mVSyncInjector = new InjectVSyncSource(); - mInjectorEventThread = new EventThread(mVSyncInjector, *this, false); + if (mInjectVSyncs == enable) { + return; } - mEventQueue.setEventThread(mInjectorEventThread); - } else { + + if (enable) { + ALOGV("VSync Injections enabled"); + if (mVSyncInjector.get() == nullptr) { + mVSyncInjector = new InjectVSyncSource(); + mInjectorEventThread = new EventThread(mVSyncInjector, *this, false); + } + mEventQueue.setEventThread(mInjectorEventThread); + } else { + ALOGV("VSync Injections disabled"); + mEventQueue.setEventThread(mSFEventThread); + } + mInjectVSyncs = enable; - ALOGV("VSync Injections disabled"); - mEventQueue.setEventThread(mSFEventThread); - mVSyncInjector.clear(); - } + }); + postMessageSync(enableVSyncInjections); return NO_ERROR; } status_t SurfaceFlinger::injectVSync(nsecs_t when) { + Mutex::Autolock _l(mStateLock); + if (!mInjectVSyncs) { ALOGE("VSync Injections not enabled"); return BAD_VALUE; @@ -3983,6 +3991,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case GET_ANIMATION_FRAME_STATS: case SET_POWER_MODE: case GET_HDR_CAPABILITIES: + case ENABLE_VSYNC_INJECTIONS: + case INJECT_VSYNC: { // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); -- cgit v1.2.3-59-g8ed1b From a76b271f0e14325fa0ebb98e1cac0a15adfea1cb Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 20 Sep 2017 12:02:26 -0700 Subject: Add captureLayers function to capture a layer and its children. The captureLayers function gets a root layer as its argument. It will capture the content for that layer and its descendants. The capture will set the root layer's transform back to (0, 0). Test: Transaction_test ScreenCaptureTest Change-Id: I84fb66a65cd91434cddc99506b1924cf9f950935 --- libs/gui/ISurfaceComposer.cpp | 24 ++ libs/gui/SurfaceComposerClient.cpp | 9 + libs/gui/include/gui/ISurfaceComposer.h | 5 + libs/gui/include/gui/SurfaceComposerClient.h | 3 + libs/gui/tests/Surface_test.cpp | 5 + services/surfaceflinger/Android.mk | 1 + services/surfaceflinger/ColorLayer.cpp | 7 +- services/surfaceflinger/ColorLayer.h | 2 +- services/surfaceflinger/DisplayDevice.h | 31 ++ services/surfaceflinger/Layer.cpp | 85 +++--- services/surfaceflinger/Layer.h | 23 +- services/surfaceflinger/RenderArea.cpp | 34 +++ services/surfaceflinger/RenderArea.h | 40 +++ services/surfaceflinger/SurfaceFlinger.cpp | 326 +++++++++++---------- services/surfaceflinger/SurfaceFlinger.h | 43 +-- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 326 +++++++++++---------- services/surfaceflinger/Transform.cpp | 19 +- services/surfaceflinger/Transform.h | 4 + services/surfaceflinger/tests/Transaction_test.cpp | 159 ++++++++++ 19 files changed, 760 insertions(+), 386 deletions(-) create mode 100644 services/surfaceflinger/RenderArea.cpp create mode 100644 services/surfaceflinger/RenderArea.h (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 96771257c1..973302c226 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -122,6 +122,18 @@ public: return reply.readInt32(); } + virtual status_t captureLayers(const sp& layerHandleBinder, + const sp& producer, + ISurfaceComposer::Rotation rotation) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(layerHandleBinder); + data.writeStrongBinder(IInterface::asBinder(producer)); + data.writeInt32(static_cast(rotation)); + remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); + return reply.readInt32(); + } + virtual bool authenticateSurfaceTexture( const sp& bufferProducer) const { @@ -588,6 +600,18 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(res); return NO_ERROR; } + case CAPTURE_LAYERS: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp layerHandleBinder = data.readStrongBinder(); + sp producer = + interface_cast(data.readStrongBinder()); + int32_t rotation = data.readInt32(); + + status_t res = captureLayers(layerHandleBinder, producer, + static_cast(rotation)); + reply->writeInt32(res); + return NO_ERROR; + } case AUTHENTICATE_SURFACE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp bufferProducer = diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 40e319e28a..15c4c9a880 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -731,6 +731,15 @@ status_t ScreenshotClient::captureToBuffer(const sp& display, return ret; } +status_t ScreenshotClient::captureLayers(const sp& layerHandle, + const sp& producer, + uint32_t rotation) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + return s->captureLayers(layerHandle, producer, + static_cast(rotation)); +} + ScreenshotClient::ScreenshotClient() : mHaveBuffer(false) { memset(&mBuffer, 0, sizeof(mBuffer)); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index b2267426a8..13e7473d54 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -174,6 +174,10 @@ public: bool useIdentityTransform, Rotation rotation = eRotateNone) = 0; + virtual status_t captureLayers(const sp& layerHandleBinder, + const sp& producer, + Rotation rotation = eRotateNone) = 0; + /* Clears the frame statistics for animations. * * Requires the ACCESS_SURFACE_FLINGER permission. @@ -226,6 +230,7 @@ public: SET_ACTIVE_CONFIG, CONNECT_DISPLAY, CAPTURE_SCREEN, + CAPTURE_LAYERS, CLEAR_ANIMATION_FRAME_STATS, GET_ANIMATION_FRAME_STATS, SET_POWER_MODE, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 00d593638d..d63dafea41 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -297,6 +297,9 @@ public: bool useIdentityTransform, uint32_t rotation, sp* outbuffer); + static status_t captureLayers(const sp& layerHandle, + const sp& producer, uint32_t rotation); + private: mutable sp mCpuConsumer; mutable sp mProducer; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 572760e77d..660680bf9e 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -529,6 +529,11 @@ public: int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/, bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } + virtual status_t captureLayers(const sp& /*parentHandle*/, + const sp& /*producer*/, + ISurfaceComposer::Rotation /*rotation*/) override { + return NO_ERROR; + } status_t clearAnimationFrameStats() override { return NO_ERROR; } status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override { return NO_ERROR; diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index d8152e08cc..d9bca04b0b 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -40,6 +40,7 @@ LOCAL_SRC_FILES := \ RenderEngine/Texture.cpp \ RenderEngine/GLES20RenderEngine.cpp \ LayerProtoHelper.cpp \ + RenderArea.cpp \ LOCAL_MODULE := libsurfaceflinger LOCAL_C_INCLUDES := \ diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 6923782b27..32526dd29b 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -40,13 +40,12 @@ ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp& client, : Layer(flinger, client, name, w, h, flags) { } -void ColorLayer::onDraw(const sp& hw, - const Region& /* clip */, bool useIdentityTransform) const -{ +void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, + bool useIdentityTransform) const { const State& s(getDrawingState()); if (s.color.a>0) { Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); - computeGeometry(hw, mesh, useIdentityTransform); + computeGeometry(renderArea, mesh, useIdentityTransform); RenderEngine& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */, true /* disableTexture */, s.color); diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index ac3e2a95dc..cdf3eca60a 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -34,7 +34,7 @@ public: virtual ~ColorLayer() = default; virtual const char* getTypeId() const { return "ColorLayer"; } - virtual void onDraw(const sp& hw, const Region& clip, + virtual void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const; virtual bool isOpaque(const Layer::State&) const { return false; } virtual bool isSecure() const { return false; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 8636e2af79..49fef5805f 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -37,7 +37,9 @@ #include #include +#include #include +#include "RenderArea.h" #ifdef USE_HWC2 #include @@ -300,6 +302,35 @@ struct DisplayDeviceState { bool isSecure = false; }; +class DisplayRenderArea : public RenderArea { +public: + DisplayRenderArea(const sp device, + ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone) + : DisplayRenderArea(device, device->getBounds(), device->getHeight(), device->getWidth(), + rotation) {} + DisplayRenderArea(const sp device, Rect sourceCrop, uint32_t reqHeight, + uint32_t reqWidth, ISurfaceComposer::Rotation rotation) + : RenderArea(reqHeight, reqWidth, rotation), mDevice(device), mSourceCrop(sourceCrop) {} + + const Transform& getTransform() const override { return mDevice->getTransform(); } + Rect getBounds() const override { return mDevice->getBounds(); } + int getHeight() const override { return mDevice->getHeight(); } + int getWidth() const override { return mDevice->getWidth(); } + bool isSecure() const override { return mDevice->isSecure(); } + bool needsFiltering() const override { return mDevice->needsFiltering(); } + Rect getSourceCrop() const override { return mSourceCrop; } +#ifdef USE_HWC2 + bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); } + android_color_mode_t getActiveColorMode() const override { + return mDevice->getActiveColorMode(); + } +#endif + +private: + const sp mDevice; + const Rect mSourceCrop; +}; + }; // namespace android #endif // ANDROID_DISPLAY_DEVICE_H diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 27739ce074..56328c9b3d 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1063,17 +1063,16 @@ Rect Layer::getPosition( // drawing... // --------------------------------------------------------------------------- -void Layer::draw(const sp& hw, const Region& clip) const { - onDraw(hw, clip, false); +void Layer::draw(const RenderArea& renderArea, const Region& clip) const { + onDraw(renderArea, clip, false); } -void Layer::draw(const sp& hw, - bool useIdentityTransform) const { - onDraw(hw, Region(hw->bounds()), useIdentityTransform); +void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) const { + onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform); } -void Layer::draw(const sp& hw) const { - onDraw(hw, Region(hw->bounds()), false); +void Layer::draw(const RenderArea& renderArea) const { + onDraw(renderArea, Region(renderArea.getBounds()), false); } static constexpr mat4 inverseOrientation(uint32_t transform) { @@ -1097,7 +1096,7 @@ static constexpr mat4 inverseOrientation(uint32_t transform) { /* * onDraw will draw the current layer onto the presentable buffer */ -void Layer::onDraw(const sp& hw, const Region& clip, +void Layer::onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const { ATRACE_CALL(); @@ -1119,12 +1118,12 @@ void Layer::onDraw(const sp& hw, const Region& clip, finished = true; return; } - under.orSelf( hw->getTransform().transform(layer->visibleRegion) ); + under.orSelf(renderArea.getTransform().transform(layer->visibleRegion)); }); // if not everything below us is covered, we plug the holes! Region holes(clip.subtract(under)); if (!holes.isEmpty()) { - clearWithOpenGL(hw, 0, 0, 0, 1); + clearWithOpenGL(renderArea, 0, 0, 0, 1); } return; } @@ -1138,13 +1137,13 @@ void Layer::onDraw(const sp& hw, const Region& clip, // is probably going to have something visibly wrong. } - bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure()); + bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure()); RenderEngine& engine(mFlinger->getRenderEngine()); if (!blackOutLayer) { // TODO: we could be more subtle with isFixedSize() - const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize(); + const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize(); // Query the texture matrix given our current filtering mode. float textureMatrix[16]; @@ -1190,31 +1189,29 @@ void Layer::onDraw(const sp& hw, const Region& clip, } else { engine.setupLayerBlackedOut(); } - drawWithOpenGL(hw, useIdentityTransform); + drawWithOpenGL(renderArea, useIdentityTransform); engine.disableTexturing(); } -void Layer::clearWithOpenGL(const sp& hw, +void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue, float alpha) const { RenderEngine& engine(mFlinger->getRenderEngine()); - computeGeometry(hw, mMesh, false); + computeGeometry(renderArea, mMesh, false); engine.setupFillWithColor(red, green, blue, alpha); engine.drawMesh(mMesh); } -void Layer::clearWithOpenGL( - const sp& hw) const { - clearWithOpenGL(hw, 0,0,0,0); +void Layer::clearWithOpenGL(const RenderArea& renderArea) const { + clearWithOpenGL(renderArea, 0,0,0,0); } -void Layer::drawWithOpenGL(const sp& hw, - bool useIdentityTransform) const { +void Layer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { const State& s(getDrawingState()); - computeGeometry(hw, mMesh, useIdentityTransform); + computeGeometry(renderArea, mMesh, useIdentityTransform); /* * NOTE: the way we compute the texture coordinates here produces @@ -1440,12 +1437,11 @@ static void boundPoint(vec2* point, const Rect& crop) { } } -void Layer::computeGeometry(const sp& hw, Mesh& mesh, - bool useIdentityTransform) const -{ +void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, + bool useIdentityTransform) const { const Layer::State& s(getDrawingState()); - const Transform hwTransform(hw->getTransform()); - const uint32_t hw_h = hw->getHeight(); + const Transform renderAreaTransform(renderArea.getTransform()); + const uint32_t height = renderArea.getHeight(); Rect win = computeBounds(); vec2 lt = vec2(win.left, win.top); @@ -1469,12 +1465,12 @@ void Layer::computeGeometry(const sp& hw, Mesh& mesh, } Mesh::VertexArray position(mesh.getPositionArray()); - position[0] = hwTransform.transform(lt); - position[1] = hwTransform.transform(lb); - position[2] = hwTransform.transform(rb); - position[3] = hwTransform.transform(rt); + position[0] = renderAreaTransform.transform(lt); + position[1] = renderAreaTransform.transform(lb); + position[2] = renderAreaTransform.transform(rb); + position[3] = renderAreaTransform.transform(rt); for (size_t i=0 ; i<4 ; i++) { - position[i].y = hw_h - position[i].y; + position[i].y = height - position[i].y; } } @@ -1512,8 +1508,8 @@ bool Layer::isCropped() const { return !mCurrentCrop.isEmpty(); } -bool Layer::needsFiltering(const sp& hw) const { - return mNeedsFiltering || hw->needsFiltering(); +bool Layer::needsFiltering(const RenderArea& renderArea) const { + return mNeedsFiltering || renderArea.needsFiltering(); } void Layer::setVisibleRegion(const Region& visibleRegion) { @@ -2773,6 +2769,29 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, } } +/** + * Traverse only children in z order, ignoring relative layers. + */ +void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet, + const LayerVector::Visitor& visitor) { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; + + size_t i = 0; + for (; i < children.size(); i++) { + const auto& relative = children[i]; + if (relative->getZ() >= 0) { + break; + } + relative->traverseChildrenInZOrder(stateSet, visitor); + } + visitor(this); + for (; i < children.size(); i++) { + const auto& relative = children[i]; + relative->traverseChildrenInZOrder(stateSet, visitor); + } +} + Transform Layer::getTransform() const { Transform t; const auto& p = mDrawingParent.promote(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 06c4863ce2..d75e175f5a 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -50,6 +50,7 @@ #include "RenderEngine/Mesh.h" #include "RenderEngine/Texture.h" #include +#include "RenderArea.h" #include @@ -255,8 +256,7 @@ public: return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay); } - void computeGeometry(const sp& hw, Mesh& mesh, - bool useIdentityTransform) const; + void computeGeometry(const RenderArea& renderArea, Mesh& mesh, bool useIdentityTransform) const; Rect computeBounds(const Region& activeTransparentRegion) const; Rect computeBounds() const; @@ -312,7 +312,7 @@ protected: /* * onDraw - draws the surface. */ - virtual void onDraw(const sp& hw, const Region& clip, + virtual void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const; public: @@ -379,9 +379,9 @@ public: * draw - performs some global clipping optimizations * and calls onDraw(). */ - void draw(const sp& hw, const Region& clip) const; - void draw(const sp& hw, bool useIdentityTransform) const; - void draw(const sp& hw) const; + void draw(const RenderArea& renderArea, const Region& clip) const; + void draw(const RenderArea& renderArea, bool useIdentityTransform) const; + void draw(const RenderArea& renderArea) const; /* * doTransaction - process the transaction. This is a good place to figure @@ -472,7 +472,7 @@ public: #endif // ----------------------------------------------------------------------- - void clearWithOpenGL(const sp& hw) const; + void clearWithOpenGL(const RenderArea& renderArea) const; void setFiltering(bool filtering); bool getFiltering() const; @@ -516,6 +516,9 @@ public: const LayerVector::Visitor& visitor); void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); + void traverseChildrenInZOrder(LayerVector::StateSet stateSet, + const LayerVector::Visitor& visitor); + size_t getChildrenCount() const; void addChild(const sp& layer); // Returns index if removed, or negative value otherwise @@ -569,7 +572,7 @@ private: void commitTransaction(const State& stateToCommit); // needsLinearFiltering - true if this surface's state requires filtering - bool needsFiltering(const sp& hw) const; + bool needsFiltering(const RenderArea& renderArea) const; uint32_t getEffectiveUsage(uint32_t usage) const; @@ -582,9 +585,9 @@ private: static bool getOpacityForFormat(uint32_t format); // drawing - void clearWithOpenGL(const sp& hw, + void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b, float alpha) const; - void drawWithOpenGL(const sp& hw, + void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const; // Temporary - Used only for LEGACY camera mode. diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp new file mode 100644 index 0000000000..6225df134d --- /dev/null +++ b/services/surfaceflinger/RenderArea.cpp @@ -0,0 +1,34 @@ +#include "RenderArea.h" + +namespace android { + +/* + * Checks that the requested width and height are valid and updates them to the render area + * dimensions if they are set to 0 + */ +status_t RenderArea::updateDimensions() { + // get screen geometry + + uint32_t width = getWidth(); + uint32_t height = getHeight(); + + if (mRotationFlags & Transform::ROT_90) { + std::swap(width, height); + } + + if ((mReqWidth > width) || (mReqHeight > height)) { + ALOGE("size mismatch (%d, %d) > (%d, %d)", mReqWidth, mReqHeight, width, height); + return BAD_VALUE; + } + + if (mReqWidth == 0) { + mReqWidth = width; + } + if (mReqHeight == 0) { + mReqHeight = height; + } + + return NO_ERROR; +} + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h new file mode 100644 index 0000000000..faf1ec64f8 --- /dev/null +++ b/services/surfaceflinger/RenderArea.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Transform.h" + +namespace android { + +class RenderArea { +public: + RenderArea(uint32_t reqHeight, uint32_t reqWidth, ISurfaceComposer::Rotation rotation) + : mReqHeight(reqHeight), mReqWidth(reqWidth) { + mRotationFlags = Transform::fromRotation(rotation); + } + + virtual ~RenderArea() = default; + + virtual const Transform& getTransform() const = 0; + virtual Rect getBounds() const = 0; + virtual int getHeight() const = 0; + virtual int getWidth() const = 0; + virtual bool isSecure() const = 0; + virtual bool needsFiltering() const = 0; + virtual Rect getSourceCrop() const = 0; + + int getReqHeight() const { return mReqHeight; }; + int getReqWidth() const { return mReqWidth; }; + Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; +#ifdef USE_HWC2 + virtual bool getWideColorSupport() const = 0; + virtual android_color_mode_t getActiveColorMode() const = 0; +#endif + + status_t updateDimensions(); + +private: + uint32_t mReqHeight; + uint32_t mReqWidth; + Transform::orientation_flags mRotationFlags; +}; + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 05c76fce46..fe9409b35e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2650,6 +2650,7 @@ bool SurfaceFlinger::doComposeSurfaces( { ALOGV("doComposeSurfaces"); + const DisplayRenderArea renderArea(displayDevice); const auto hwcId = displayDevice->getHwcDisplayId(); mat4 oldColorMatrix; @@ -2759,12 +2760,12 @@ bool SurfaceFlinger::doComposeSurfaces( && hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared - layer->clearWithOpenGL(displayDevice); + layer->clearWithOpenGL(renderArea); } break; } case HWC2::Composition::Client: { - layer->draw(displayDevice, clip); + layer->draw(renderArea, clip); break; } default: @@ -2781,7 +2782,7 @@ bool SurfaceFlinger::doComposeSurfaces( const Region clip(dirty.intersect( displayTransform.transform(layer->visibleRegion))); if (!clip.isEmpty()) { - layer->draw(displayDevice, clip); + layer->draw(renderArea, clip); } } } @@ -4029,6 +4030,17 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { } break; } + case CAPTURE_LAYERS: { + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int uid = ipc->getCallingUid(); + if ((uid != AID_GRAPHICS) && + !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) { + ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + break; + } } return OK; } @@ -4228,35 +4240,6 @@ void SurfaceFlinger::repaintEverything() { repaintEverythingLocked(); } -// Checks that the requested width and height are valid and updates them to the display dimensions -// if they are set to 0 -static status_t updateDimensionsLocked(const sp& displayDevice, - Transform::orientation_flags rotation, - uint32_t* requestedWidth, uint32_t* requestedHeight) { - // get screen geometry - uint32_t displayWidth = displayDevice->getWidth(); - uint32_t displayHeight = displayDevice->getHeight(); - - if (rotation & Transform::ROT_90) { - std::swap(displayWidth, displayHeight); - } - - if ((*requestedWidth > displayWidth) || (*requestedHeight > displayHeight)) { - ALOGE("size mismatch (%d, %d) > (%d, %d)", - *requestedWidth, *requestedHeight, displayWidth, displayHeight); - return BAD_VALUE; - } - - if (*requestedWidth == 0) { - *requestedWidth = displayWidth; - } - if (*requestedHeight == 0) { - *requestedHeight = displayHeight; - } - - return NO_ERROR; -} - // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope class WindowDisconnector { public: @@ -4305,50 +4288,86 @@ static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth, } status_t SurfaceFlinger::captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { + const sp& producer, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, + int32_t maxLayerZ, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); - if (CC_UNLIKELY(display == 0)) - return BAD_VALUE; + if (CC_UNLIKELY(display == 0)) return BAD_VALUE; + + const sp device(getDisplayDeviceLocked(display)); + DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation); + + auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, + device, minLayerZ, maxLayerZ, std::placeholders::_1); + return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform); +} + +status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, + const sp& producer, + ISurfaceComposer::Rotation rotation) { + ATRACE_CALL(); + + class LayerRenderArea : public RenderArea { + public: + LayerRenderArea(const sp& layer, ISurfaceComposer::Rotation rotation) + : RenderArea(layer->getCurrentState().active.h, layer->getCurrentState().active.w, + rotation), + mLayer(layer) {} + const Transform& getTransform() const override { + // Make the top level transform the inverse the transform and it's parent so it sets + // the whole capture back to 0,0 + return *new Transform(mLayer->getTransform().inverse()); + } + Rect getBounds() const override { + const Layer::State& layerState(mLayer->getDrawingState()); + return Rect(layerState.active.w, layerState.active.h); + } + int getHeight() const override { return mLayer->getDrawingState().active.h; } + int getWidth() const override { return mLayer->getDrawingState().active.w; } + bool isSecure() const override { return false; } + bool needsFiltering() const override { return false; } + + Rect getSourceCrop() const override { return getBounds(); } + bool getWideColorSupport() const override { return false; } + android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; } + + private: + const sp& mLayer; + }; + + auto layerHandle = reinterpret_cast(layerHandleBinder.get()); + auto parent = layerHandle->owner.promote(); + + LayerRenderArea renderArea(parent, rotation); + auto traverseLayers = [parent](const LayerVector::Visitor& visitor) { + parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + if (!layer->isVisible()) { + return; + } + visitor(layer); + }); + }; + return captureScreenCommon(renderArea, traverseLayers, producer, false); +} + +status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + const sp& producer, + bool useIdentityTransform) { + ATRACE_CALL(); if (CC_UNLIKELY(producer == 0)) return BAD_VALUE; + renderArea.updateDimensions(); + // if we have secure windows on this display, never allow the screen capture // unless the producer interface is local (i.e.: we can take a screenshot for // ourselves). bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder(); - // Convert to surfaceflinger's internal rotation type. - Transform::orientation_flags rotationFlags; - switch (rotation) { - case ISurfaceComposer::eRotateNone: - rotationFlags = Transform::ROT_0; - break; - case ISurfaceComposer::eRotate90: - rotationFlags = Transform::ROT_90; - break; - case ISurfaceComposer::eRotate180: - rotationFlags = Transform::ROT_180; - break; - case ISurfaceComposer::eRotate270: - rotationFlags = Transform::ROT_270; - break; - default: - rotationFlags = Transform::ROT_0; - ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); - break; - } - - { // Autolock scope - Mutex::Autolock lock(mStateLock); - sp displayDevice(getDisplayDeviceLocked(display)); - updateDimensionsLocked(displayDevice, rotationFlags, &reqWidth, &reqHeight); - } - // create a surface (because we're a producer, and we need to // dequeue/queue a buffer) sp surface = new Surface(producer, false); @@ -4369,9 +4388,9 @@ status_t SurfaceFlinger::captureScreen(const sp& display, WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL); ANativeWindowBuffer* buffer = nullptr; - result = getWindowBuffer(window, reqWidth, reqHeight, - hasWideColorDisplay && !mForceNativeColorMode, - getRenderEngine().usesWideColor(), &buffer); + result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(), + hasWideColorDisplay && !mForceNativeColorMode, + getRenderEngine().usesWideColor(), &buffer); if (result != NO_ERROR) { return result; } @@ -4399,10 +4418,8 @@ status_t SurfaceFlinger::captureScreen(const sp& display, int fd = -1; { Mutex::Autolock _l(mStateLock); - sp device(getDisplayDeviceLocked(display)); - result = captureScreenImplLocked(device, buffer, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, - rotationFlags, isLocalScreenshot, &fd); + result = captureScreenImplLocked(renderArea, traverseLayers, buffer, + useIdentityTransform, isLocalScreenshot, &fd); } { @@ -4431,84 +4448,66 @@ status_t SurfaceFlinger::captureScreen(const sp& display, // queueBuffer takes ownership of syncFd result = window->queueBuffer(window, buffer, syncFd); } - return result; } - -void SurfaceFlinger::renderScreenImplLocked( - const sp& hw, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation) -{ +void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, bool yswap, + bool useIdentityTransform) { ATRACE_CALL(); + RenderEngine& engine(getRenderEngine()); // get screen geometry - const int32_t hw_w = hw->getWidth(); - const int32_t hw_h = hw->getHeight(); - const bool filtering = static_cast(reqWidth) != hw_w || - static_cast(reqHeight) != hw_h; + const auto raWidth = renderArea.getWidth(); + const auto raHeight = renderArea.getHeight(); + + const auto reqWidth = renderArea.getReqWidth(); + const auto reqHeight = renderArea.getReqHeight(); + Rect sourceCrop = renderArea.getSourceCrop(); + + const bool filtering = static_cast(reqWidth) != raWidth || + static_cast(reqHeight) != raHeight; // if a default or invalid sourceCrop is passed in, set reasonable values - if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || - !sourceCrop.isValid()) { + if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || !sourceCrop.isValid()) { sourceCrop.setLeftTop(Point(0, 0)); - sourceCrop.setRightBottom(Point(hw_w, hw_h)); + sourceCrop.setRightBottom(Point(raWidth, raHeight)); } // ensure that sourceCrop is inside screen if (sourceCrop.left < 0) { ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left); } - if (sourceCrop.right > hw_w) { - ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w); + if (sourceCrop.right > raWidth) { + ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, raWidth); } if (sourceCrop.top < 0) { ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top); } - if (sourceCrop.bottom > hw_h) { - ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h); + if (sourceCrop.bottom > raHeight) { + ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight); } -#ifdef USE_HWC2 - engine.setWideColor(hw->getWideColorSupport() && !mForceNativeColorMode); - engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : hw->getActiveColorMode()); -#endif + engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode); + engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode()); // make sure to clear all GL error flags engine.checkErrors(); // set-up our viewport - engine.setViewportAndProjection( - reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation); + engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, raHeight, yswap, + renderArea.getRotationFlags()); engine.disableTexturing(); // redraw the screen entirely... engine.clearWithColor(0, 0, 0, 1); - // We loop through the first level of layers without traversing, - // as we need to interpret min/max layer Z in the top level Z space. - for (const auto& layer : mDrawingState.layersSortedByZ) { - if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { - continue; - } - const Layer::State& state(layer->getDrawingState()); - if (state.z < minLayerZ || state.z > maxLayerZ) { - continue; - } - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - if (!layer->isVisible()) { - return; - } - if (filtering) layer->setFiltering(true); - layer->draw(hw, useIdentityTransform); - if (filtering) layer->setFiltering(false); - }); - } - - hw->setViewportAndProjection(); + traverseLayers([&](Layer* layer) { + if (filtering) layer->setFiltering(true); + layer->draw(renderArea, useIdentityTransform); + if (filtering) layer->setFiltering(false); + }); } // A simple RAII class that holds an EGLImage and destroys it either: @@ -4531,27 +4530,18 @@ private: EGLImageKHR mImage; }; -status_t SurfaceFlinger::captureScreenImplLocked(const sp& hw, - ANativeWindowBuffer* buffer, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - Transform::orientation_flags rotation, - bool isLocalScreenshot, int* outSyncFd) { +status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + ANativeWindowBuffer* buffer, + bool useIdentityTransform, bool isLocalScreenshot, + int* outSyncFd) { ATRACE_CALL(); bool secureLayerIsVisible = false; - for (const auto& layer : mDrawingState.layersSortedByZ) { - const Layer::State& state(layer->getDrawingState()); - if (!layer->belongsToDisplay(hw->getLayerStack(), false) || - (state.z < minLayerZ || state.z > maxLayerZ)) { - continue; - } - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer *layer) { - secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && - layer->isSecure()); - }); - } + + traverseLayers([&](Layer* layer) { + secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure()); + }); if (!isLocalScreenshot && secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); @@ -4582,9 +4572,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const sp& // via an FBO, which means we didn't have to create // an EGLSurface and therefore we're not // dependent on the context's EGLConfig. - renderScreenImplLocked( - hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true, - useIdentityTransform, rotation); + renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform); // Attempt to create a sync khr object that can produce a sync point. If that // isn't available, create a non-dupable sync object in the fallback path and @@ -4625,46 +4613,40 @@ status_t SurfaceFlinger::captureScreenImplLocked(const sp& *outSyncFd = syncFd; if (DEBUG_SCREENSHOTS) { + const auto reqWidth = renderArea.getReqWidth(); + const auto reqHeight = renderArea.getReqHeight(); + uint32_t* pixels = new uint32_t[reqWidth*reqHeight]; getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels); - checkScreenshot(reqWidth, reqHeight, reqWidth, pixels, - hw, minLayerZ, maxLayerZ); + checkScreenshot(reqWidth, reqHeight, reqWidth, pixels, traverseLayers); delete [] pixels; } // destroy our image imageHolder.destroy(); - return NO_ERROR; } void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, - const sp& hw, int32_t minLayerZ, int32_t maxLayerZ) { + TraverseLayersFunction traverseLayers) { if (DEBUG_SCREENSHOTS) { - for (size_t y=0 ; ygetLayerStack()); + ALOGE("*** we just took a black screenshot ***"); size_t i = 0; - for (const auto& layer : mDrawingState.layersSortedByZ) { + traverseLayers([&](Layer* layer) { const Layer::State& state(layer->getDrawingState()); - if (layer->belongsToDisplay(hw->getLayerStack(), false) && state.z >= minLayerZ && - state.z <= maxLayerZ) { - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", - layer->isVisible() ? '+' : '-', - i, layer->getName().string(), layer->getLayerStack(), state.z, - layer->isVisible(), state.flags, static_cast(state.color.a)); - i++; - }); - } - } + ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", + layer->isVisible() ? '+' : '-', i, layer->getName().string(), + layer->getLayerStack(), state.z, layer->isVisible(), state.flags, + static_cast(state.color.a)); + i++; + }); } } @@ -4678,6 +4660,28 @@ void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& layersSortedByZ.traverseInReverseZOrder(stateSet, visitor); } +void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, int32_t minLayerZ, + int32_t maxLayerZ, + const LayerVector::Visitor& visitor) { + // We loop through the first level of layers without traversing, + // as we need to interpret min/max layer Z in the top level Z space. + for (const auto& layer : mDrawingState.layersSortedByZ) { + if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { + continue; + } + const Layer::State& state(layer->getDrawingState()); + if (state.z < minLayerZ || state.z > maxLayerZ) { + continue; + } + layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + if (!layer->isVisible()) { + return; + } + visitor(layer); + }); + } +} + }; // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bd98c8f0e0..9975de9252 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -77,6 +77,7 @@ #include #include #include +#include "RenderArea.h" #include @@ -97,6 +98,8 @@ class EventControlThread; class VSyncSource; class InjectVSyncSource; +typedef std::function TraverseLayersFunction; + namespace dvr { class VrFlinger; } // namespace dvr @@ -303,6 +306,9 @@ private: Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation); + virtual status_t captureLayers(const sp& parentHandle, + const sp& producer, + ISurfaceComposer::Rotation rotation); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp& display, @@ -448,28 +454,26 @@ private: void startBootAnim(); - void renderScreenImplLocked( - const sp& hw, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation); + void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, + bool yswap, bool useIdentityTransform); + + status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, + const sp& producer, + bool useIdentityTransform); #ifdef USE_HWC2 - status_t captureScreenImplLocked(const sp& device, - ANativeWindowBuffer* buffer, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, - int32_t maxLayerZ, bool useIdentityTransform, - Transform::orientation_flags rotation, bool isLocalScreenshot, - int* outSyncFd); + status_t captureScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + ANativeWindowBuffer* buffer, bool useIdentityTransform, + bool isLocalScreenshot, int* outSyncFd); #else - status_t captureScreenImplLocked( - const sp& hw, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation, - bool isLocalScreenshot); + status_t captureScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + const sp& producer, + bool useIdentityTransform, bool isLocalScreenshot); #endif + void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, + int32_t maxLayerZ, const LayerVector::Visitor& visitor); sp mStartPropertySetThread = nullptr; @@ -613,8 +617,7 @@ private: bool startDdmConnection(); void appendSfConfigString(String8& result) const; void checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, - const sp& hw, - int32_t minLayerZ, int32_t maxLayerZ); + TraverseLayersFunction traverseLayers); void logFrameStats(); diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index ed7641fe99..8c530e0f61 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -2212,6 +2212,8 @@ void SurfaceFlinger::doDisplayComposition(const sp& hw, bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const Region& dirty) { + DisplayRenderArea renderArea(hw); + RenderEngine& engine(getRenderEngine()); const int32_t id = hw->getHwcDisplayId(); HWComposer& hwc(getHwComposer()); @@ -2303,12 +2305,12 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const && hasGlesComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared - layer->clearWithOpenGL(hw); + layer->clearWithOpenGL(renderArea); } break; } case HWC_FRAMEBUFFER: { - layer->draw(hw, clip); + layer->draw(renderArea, clip); break; } case HWC_FRAMEBUFFER_TARGET: { @@ -2328,7 +2330,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const const Region clip(dirty.intersect( tr.transform(layer->visibleRegion))); if (!clip.isEmpty()) { - layer->draw(hw, clip); + layer->draw(renderArea, clip); } } } @@ -3493,6 +3495,18 @@ status_t SurfaceFlinger::onTransact( } break; } + case CAPTURE_LAYERS: + { + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int uid = ipc->getCallingUid(); + if ((uid != AID_GRAPHICS) && + !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) { + ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + break; + } } status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags); @@ -3766,16 +3780,72 @@ public: } }; - status_t SurfaceFlinger::captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { - + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { + ATRACE_CALL(); if (CC_UNLIKELY(display == 0)) return BAD_VALUE; + const sp device(getDisplayDeviceLocked(display)); + DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation); + + auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, + device, minLayerZ, maxLayerZ, std::placeholders::_1); + return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform); +} + +status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, + const sp& producer, + ISurfaceComposer::Rotation rotation) { + ATRACE_CALL(); + class LayerRenderArea : public RenderArea { + public: + LayerRenderArea(const sp& layer, ISurfaceComposer::Rotation rotation) + : RenderArea(layer->getCurrentState().active.h, layer->getCurrentState().active.w, + rotation), + mLayer(layer) {} + const Transform& getTransform() const override { + // Make the top level transform the inverse the transform and it's parent so it sets + // the whole capture back to 0,0 + return *new Transform(mLayer->getTransform().inverse()); + } + Rect getBounds() const override { + const Layer::State& layerState(mLayer->getDrawingState()); + return Rect(layerState.active.w, layerState.active.h); + } + int getHeight() const override { return mLayer->getDrawingState().active.h; } + int getWidth() const override { return mLayer->getDrawingState().active.w; } + bool isSecure() const override { return false; } + bool needsFiltering() const override { return false; } + + Rect getSourceCrop() const override { return getBounds(); } + + private: + const sp& mLayer; + }; + + auto layerHandle = reinterpret_cast(layerHandleBinder.get()); + auto parent = layerHandle->owner.promote(); + + LayerRenderArea renderArea(parent, rotation); + auto traverseLayers = [parent](const LayerVector::Visitor& visitor) { + parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + if (!layer->isVisible()) { + return; + } + visitor(layer); + }); + }; + return captureScreenCommon(renderArea, traverseLayers, producer, false); +} + +status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + const sp& producer, + bool useIdentityTransform) { if (CC_UNLIKELY(producer == 0)) return BAD_VALUE; @@ -3784,64 +3854,33 @@ status_t SurfaceFlinger::captureScreen(const sp& display, // ourselves). bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder(); - // Convert to surfaceflinger's internal rotation type. - Transform::orientation_flags rotationFlags; - switch (rotation) { - case ISurfaceComposer::eRotateNone: - rotationFlags = Transform::ROT_0; - break; - case ISurfaceComposer::eRotate90: - rotationFlags = Transform::ROT_90; - break; - case ISurfaceComposer::eRotate180: - rotationFlags = Transform::ROT_180; - break; - case ISurfaceComposer::eRotate270: - rotationFlags = Transform::ROT_270; - break; - default: - rotationFlags = Transform::ROT_0; - ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); - break; - } - class MessageCaptureScreen : public MessageBase { SurfaceFlinger* flinger; - sp display; + const RenderArea* renderArea; + TraverseLayersFunction traverseLayers; sp producer; - Rect sourceCrop; - uint32_t reqWidth, reqHeight; - int32_t minLayerZ,maxLayerZ; bool useIdentityTransform; - Transform::orientation_flags rotation; status_t result; bool isLocalScreenshot; public: - MessageCaptureScreen(SurfaceFlinger* flinger, - const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - Transform::orientation_flags rotation, - bool isLocalScreenshot) - : flinger(flinger), display(display), producer(producer), - sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight), - minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), - useIdentityTransform(useIdentityTransform), - rotation(rotation), result(PERMISSION_DENIED), - isLocalScreenshot(isLocalScreenshot) - { - } + MessageCaptureScreen(SurfaceFlinger* flinger, const RenderArea* renderArea, + TraverseLayersFunction traverseLayers, + const sp& producer, bool useIdentityTransform, + bool isLocalScreenshot) + : flinger(flinger), + renderArea(renderArea), + traverseLayers(traverseLayers), + producer(producer), + useIdentityTransform(useIdentityTransform), + result(PERMISSION_DENIED), + isLocalScreenshot(isLocalScreenshot) {} status_t getResult() const { return result; } virtual bool handler() { Mutex::Autolock _l(flinger->mStateLock); - sp hw(flinger->getDisplayDeviceLocked(display)); - result = flinger->captureScreenImplLocked(hw, producer, - sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, rotation, isLocalScreenshot); + result = flinger->captureScreenImplLocked(*renderArea, traverseLayers, producer, + useIdentityTransform, isLocalScreenshot); static_cast(IInterface::asBinder(producer).get())->exit(result); return true; } @@ -3855,9 +3894,8 @@ status_t SurfaceFlinger::captureScreen(const sp& display, // the asInterface() call below creates our "fake" BpGraphicBufferProducer // which does the marshaling work forwards to our "fake remote" above. sp msg = new MessageCaptureScreen(this, - display, IGraphicBufferProducer::asInterface( wrapper ), - sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, rotationFlags, isLocalScreenshot); + &renderArea, traverseLayers, IGraphicBufferProducer::asInterface( wrapper ), + useIdentityTransform, isLocalScreenshot); status_t res = postMessageAsync(msg); if (res == NO_ERROR) { @@ -3866,41 +3904,42 @@ status_t SurfaceFlinger::captureScreen(const sp& display, return res; } - -void SurfaceFlinger::renderScreenImplLocked( - const sp& hw, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation) +void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, + bool yswap, bool useIdentityTransform) { ATRACE_CALL(); RenderEngine& engine(getRenderEngine()); // get screen geometry - const int32_t hw_w = hw->getWidth(); - const int32_t hw_h = hw->getHeight(); - const bool filtering = static_cast(reqWidth) != hw_w || - static_cast(reqHeight) != hw_h; + const auto raWidth = renderArea.getWidth(); + const auto raHeight = renderArea.getHeight(); + + const auto reqWidth = renderArea.getReqWidth(); + const auto reqHeight = renderArea.getReqHeight(); + Rect sourceCrop = renderArea.getSourceCrop(); + + const bool filtering = static_cast(reqWidth) != raWidth || + static_cast(reqHeight) != raHeight; // if a default or invalid sourceCrop is passed in, set reasonable values if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || !sourceCrop.isValid()) { sourceCrop.setLeftTop(Point(0, 0)); - sourceCrop.setRightBottom(Point(hw_w, hw_h)); + sourceCrop.setRightBottom(Point(raWidth, raHeight)); } // ensure that sourceCrop is inside screen if (sourceCrop.left < 0) { ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left); } - if (sourceCrop.right > hw_w) { - ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w); + if (sourceCrop.right > raWidth) { + ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, raWidth); } if (sourceCrop.top < 0) { ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top); } - if (sourceCrop.bottom > hw_h) { - ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h); + if (sourceCrop.bottom > raHeight) { + ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight); } // make sure to clear all GL error flags @@ -3908,77 +3947,35 @@ void SurfaceFlinger::renderScreenImplLocked( // set-up our viewport engine.setViewportAndProjection( - reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation); + reqWidth, reqHeight, sourceCrop, raHeight, yswap, renderArea.getRotationFlags()); engine.disableTexturing(); // redraw the screen entirely... engine.clearWithColor(0, 0, 0, 1); - // We loop through the first level of layers without traversing, - // as we need to interpret min/max layer Z in the top level Z space. - for (const auto& layer : mDrawingState.layersSortedByZ) { - if (layer->getLayerStack() != hw->getLayerStack()) { - continue; - } - const Layer::State& state(layer->getDrawingState()); - if (state.z < minLayerZ || state.z > maxLayerZ) { - continue; - } - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - if (!layer->isVisible()) { - return; - } - if (filtering) layer->setFiltering(true); - layer->draw(hw, useIdentityTransform); - if (filtering) layer->setFiltering(false); - }); - } + traverseLayers([&](Layer* layer) { + if (filtering) layer->setFiltering(true); + layer->draw(renderArea, useIdentityTransform); + if (filtering) layer->setFiltering(false); + }); // compositionComplete is needed for older driver - hw->compositionComplete(); - hw->setViewportAndProjection(); +// hw->compositionComplete(); +// hw->setViewportAndProjection(); } - -status_t SurfaceFlinger::captureScreenImplLocked( - const sp& hw, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, Transform::orientation_flags rotation, - bool isLocalScreenshot) -{ +status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + const sp& producer, + bool useIdentityTransform, + bool isLocalScreenshot) { ATRACE_CALL(); - // get screen geometry - uint32_t hw_w = hw->getWidth(); - uint32_t hw_h = hw->getHeight(); - - if (rotation & Transform::ROT_90) { - std::swap(hw_w, hw_h); - } - - if ((reqWidth > hw_w) || (reqHeight > hw_h)) { - ALOGE("size mismatch (%d, %d) > (%d, %d)", - reqWidth, reqHeight, hw_w, hw_h); - return BAD_VALUE; - } - - reqWidth = (!reqWidth) ? hw_w : reqWidth; - reqHeight = (!reqHeight) ? hw_h : reqHeight; - bool secureLayerIsVisible = false; - for (const auto& layer : mDrawingState.layersSortedByZ) { - const Layer::State& state(layer->getDrawingState()); - if ((layer->getLayerStack() != hw->getLayerStack()) || - (state.z < minLayerZ || state.z > maxLayerZ)) { - continue; - } - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer *layer) { - secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && - layer->isSecure()); - }); - } + traverseLayers([&](Layer *layer) { + secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && + layer->isSecure()); + }); if (!isLocalScreenshot && secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); @@ -3996,7 +3993,8 @@ status_t SurfaceFlinger::captureScreenImplLocked( GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; int err = 0; - err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight); + err = native_window_set_buffers_dimensions(window, renderArea.getReqWidth(), + renderArea.getReqHeight()); err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); err |= native_window_set_usage(window, usage); @@ -4022,9 +4020,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( // via an FBO, which means we didn't have to create // an EGLSurface and therefore we're not // dependent on the context's EGLConfig. - renderScreenImplLocked( - hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true, - useIdentityTransform, rotation); + renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform); // Attempt to create a sync khr object that can produce a sync point. If that // isn't available, create a non-dupable sync object in the fallback path and @@ -4064,10 +4060,12 @@ status_t SurfaceFlinger::captureScreenImplLocked( } } if (DEBUG_SCREENSHOTS) { - uint32_t* pixels = new uint32_t[reqWidth*reqHeight]; - getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels); - checkScreenshot(reqWidth, reqHeight, reqWidth, pixels, - hw, minLayerZ, maxLayerZ); + uint32_t* pixels = new uint32_t[renderArea.getReqWidth() * + renderArea.getReqHeight()]; + getRenderEngine().readPixels(0, 0, renderArea.getReqWidth(), + renderArea.getReqHeight(), pixels); + checkScreenshot(renderArea.getReqWidth(), renderArea.getReqHeight(), + renderArea.getReqWidth(), pixels, traverseLayers); delete [] pixels; } @@ -4097,7 +4095,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( } void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, - const sp& hw, int32_t minLayerZ, int32_t maxLayerZ) { + TraverseLayersFunction traverseLayers) { if (DEBUG_SCREENSHOTS) { for (size_t y=0 ; ygetLayerStack()); + ALOGE("*** we just took a black screenshot ***"); + size_t i = 0; - for (const auto& layer : mDrawingState.layersSortedByZ) { + traverseLayers([&](Layer* layer) { const Layer::State& state(layer->getDrawingState()); - if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ && - state.z <= maxLayerZ) { - layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", - layer->isVisible() ? '+' : '-', - i, layer->getName().string(), layer->getLayerStack(), state.z, - layer->isVisible(), state.flags, static_cast(state.color.a)); - i++; - }); - } - } + ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", + layer->isVisible() ? '+' : '-', + i, layer->getName().string(), layer->getLayerStack(), state.z, + layer->isVisible(), state.flags, static_cast(state.color.a)); + i++; + }); } } @@ -4135,6 +4127,28 @@ void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& layersSortedByZ.traverseInReverseZOrder(stateSet, visitor); } +void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, + int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor) { + + // We loop through the first level of layers without traversing, + // as we need to interpret min/max layer Z in the top level Z space. + for (const auto& layer : mDrawingState.layersSortedByZ) { + if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { + continue; + } + const Layer::State& state(layer->getDrawingState()); + if (state.z < minLayerZ || state.z > maxLayerZ) { + continue; + } + layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + if (!layer->isVisible()) { + return; + } + visitor(layer); + }); + } +} + }; // namespace android diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index 6be9ae2c5f..37925a1641 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -20,8 +20,8 @@ #include #include -#include "clz.h" #include "Transform.h" +#include "clz.h" // --------------------------------------------------------------------------- @@ -388,6 +388,23 @@ void Transform::dump(const char* name) const ALOGD("%.4f %.4f %.4f", m[0][2], m[1][2], m[2][2]); } +Transform::orientation_flags Transform::fromRotation(ISurfaceComposer::Rotation rotation) { + // Convert to surfaceflinger's internal rotation type. + switch (rotation) { + case ISurfaceComposer::eRotateNone: + return Transform::ROT_0; + case ISurfaceComposer::eRotate90: + return Transform::ROT_90; + case ISurfaceComposer::eRotate180: + return Transform::ROT_180; + case ISurfaceComposer::eRotate270: + return Transform::ROT_270; + default: + ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); + return Transform::ROT_0; + } +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h index 6640a13839..bfc66eccb9 100644 --- a/services/surfaceflinger/Transform.h +++ b/services/surfaceflinger/Transform.h @@ -25,6 +25,8 @@ #include #include +#include + #include namespace android { @@ -51,6 +53,8 @@ public: ROT_INVALID = 0x80 }; + static orientation_flags fromRotation(ISurfaceComposer::Rotation rotation); + enum type_mask { IDENTITY = 0, TRANSLATE = 0x1, diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index f61a978487..ec87eeec77 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -116,6 +116,60 @@ private: CpuConsumer::LockedBuffer mBuf; }; +class CaptureLayer { +public: + static void captureScreen(std::unique_ptr* sc, sp& parentHandle) { + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); + sp sf(ComposerService::getComposerService()); + sp display(sf->getBuiltInDisplay( + ISurfaceComposer::eDisplayIdMain)); + SurfaceComposerClient::Transaction().apply(true); + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer)); + *sc = std::make_unique(cpuConsumer); + } + + void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuffer.format); + const uint8_t* img = static_cast(mBuffer.data); + const uint8_t* pixel = img + (4 * (y * mBuffer.stride + x)); + if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { + String8 err(String8::format("pixel @ (%3d, %3d): " + "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", + x, y, r, g, b, pixel[0], pixel[1], pixel[2])); + EXPECT_EQ(String8(), err) << err.string(); + } + } + + void expectFGColor(uint32_t x, uint32_t y) { + checkPixel(x, y, 195, 63, 63); + } + + void expectBGColor(uint32_t x, uint32_t y) { + checkPixel(x, y, 63, 63, 195); + } + + void expectChildColor(uint32_t x, uint32_t y) { + checkPixel(x, y, 200, 200, 200); + } + + CaptureLayer(const sp& cc) : + mCC(cc) { + EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuffer)); + } + + ~CaptureLayer() { + mCC->unlockBuffer(mBuffer); + } + +private: + sp mCC; + CpuConsumer::LockedBuffer mBuffer; +}; + + class LayerUpdateTest : public ::testing::Test { protected: virtual void SetUp() { @@ -1431,4 +1485,109 @@ TEST_F(LayerColorTest, ColorLayerWithNoColor) { } } +class ScreenCaptureTest : public LayerUpdateTest { +protected: + std::unique_ptr mCapture; +}; + +TEST_F(ScreenCaptureTest, CaptureSingleLayer) { + auto bgHandle = mBGSurfaceControl->getHandle(); + CaptureLayer::captureScreen(&mCapture, bgHandle); + mCapture->expectBGColor(0, 0); + // Doesn't capture FG layer which is at 64, 64 + mCapture->expectBGColor(64, 64); +} + +TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp child = mComposerClient->createSurface( + String8("Child surface"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + + SurfaceComposerClient::Transaction() + .show(child) + .apply(true); + + // Captures mFGSurfaceControl layer and its child. + CaptureLayer::captureScreen(&mCapture, fgHandle); + mCapture->expectFGColor(10, 10); + mCapture->expectChildColor(0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp child = mComposerClient->createSurface( + String8("Child surface"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + + sp grandchild = mComposerClient->createSurface( + String8("Grandchild surface"), 5, 5, + PIXEL_FORMAT_RGBA_8888, 0, child.get()); + + fillSurfaceRGBA8(grandchild, 50, 50, 50); + SurfaceComposerClient::Transaction() + .show(child) + .setPosition(grandchild, 5, 5) + .show(grandchild) + .apply(true); + + // Captures mFGSurfaceControl, its child, and the grandchild. + CaptureLayer::captureScreen(&mCapture, fgHandle); + mCapture->expectFGColor(10, 10); + mCapture->expectChildColor(0, 0); + mCapture->checkPixel(5, 5, 50, 50, 50); +} + +TEST_F(ScreenCaptureTest, CaptureChildOnly) { + sp child = mComposerClient->createSurface( + String8("Child surface"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + auto childHandle = child->getHandle(); + + SurfaceComposerClient::Transaction() + .setPosition(child, 5, 5) + .show(child) + .apply(true); + + // Captures only the child layer, and not the parent. + CaptureLayer::captureScreen(&mCapture, childHandle); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(9, 9); +} + +TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { + sp child = mComposerClient->createSurface( + String8("Child surface"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + auto childHandle = child->getHandle(); + + sp grandchild = mComposerClient->createSurface( + String8("Grandchild surface"), 5, 5, + PIXEL_FORMAT_RGBA_8888, 0, child.get()); + fillSurfaceRGBA8(grandchild, 50, 50, 50); + + SurfaceComposerClient::Transaction() + .show(child) + .setPosition(grandchild, 5, 5) + .show(grandchild) + .apply(true); + + auto grandchildHandle = grandchild->getHandle(); + + // Captures only the grandchild. + CaptureLayer::captureScreen(&mCapture, grandchildHandle); + mCapture->checkPixel(0, 0, 50, 50, 50); + mCapture->checkPixel(4, 4, 50, 50, 50); +} + } -- cgit v1.2.3-59-g8ed1b From 6200eacdc927776483d775562db11cce284cc7e0 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 5 Oct 2017 14:24:41 -0700 Subject: surfaceflinger: make vsync injection more robust There are more issues than I expected :) - no lock to synchronize enable/disable and injection - Every time injection is diabled and enabled, a new EventThread is created - mCallback might be nullptr - ENABLE_VSYNC_INJECTIONS/INJECT_VSYNC should require special permission - MessageQueue::setEventThread must be called from the main thread - MessageQueue::setEventThread does not handle EventThread switch well Bug: 65483324 Test: manual Merged-In: I7d7b98d1f57afc64af0f2065a9bc7c8ad004ca9f Change-Id: I7d7b98d1f57afc64af0f2065a9bc7c8ad004ca9f --- services/surfaceflinger/MessageQueue.cpp | 8 +++++++ services/surfaceflinger/SurfaceFlinger.cpp | 37 ++++++++++++++++++++++++------ services/surfaceflinger/SurfaceFlinger.h | 3 +++ 3 files changed, 41 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp index bca3430794..0b1199c2d0 100644 --- a/services/surfaceflinger/MessageQueue.cpp +++ b/services/surfaceflinger/MessageQueue.cpp @@ -91,6 +91,14 @@ void MessageQueue::init(const sp& flinger) void MessageQueue::setEventThread(const sp& eventThread) { + if (mEventThread == eventThread) { + return; + } + + if (mEventTube.getFd() >= 0) { + mLooper->removeFd(mEventTube.getFd()); + } + mEventThread = eventThread; mEvents = eventThread->createEventConnection(); mEvents->stealReceiveChannel(&mEventTube); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 29e7bd6792..8a8fa01571 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -515,7 +515,9 @@ public: virtual void onInjectSyncEvent(nsecs_t when) { std::lock_guard lock(mCallbackMutex); - mCallback->onVSyncEvent(when); + if (mCallback != nullptr) { + mCallback->onVSyncEvent(when); + } } virtual void setVSyncEnabled(bool) {} @@ -988,13 +990,14 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp& display, return NO_ERROR; } -status_t SurfaceFlinger::enableVSyncInjections(bool enable) { - if (enable == mInjectVSyncs) { - return NO_ERROR; +void SurfaceFlinger::enableVSyncInjectionsInternal(bool enable) { + Mutex::Autolock _l(mStateLock); + + if (mInjectVSyncs == enable) { + return; } if (enable) { - mInjectVSyncs = enable; ALOGV("VSync Injections enabled"); if (mVSyncInjector.get() == nullptr) { mVSyncInjector = new InjectVSyncSource(); @@ -1002,15 +1005,33 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) { } mEventQueue.setEventThread(mInjectorEventThread); } else { - mInjectVSyncs = enable; ALOGV("VSync Injections disabled"); mEventQueue.setEventThread(mSFEventThread); - mVSyncInjector.clear(); } + + mInjectVSyncs = enable; +} + +status_t SurfaceFlinger::enableVSyncInjections(bool enable) { + class MessageEnableVSyncInjections : public MessageBase { + SurfaceFlinger* mFlinger; + bool mEnable; + public: + MessageEnableVSyncInjections(SurfaceFlinger* flinger, bool enable) + : mFlinger(flinger), mEnable(enable) { } + virtual bool handler() { + mFlinger->enableVSyncInjectionsInternal(mEnable); + return true; + } + }; + sp msg = new MessageEnableVSyncInjections(this, enable); + postMessageSync(msg); return NO_ERROR; } status_t SurfaceFlinger::injectVSync(nsecs_t when) { + Mutex::Autolock _l(mStateLock); + if (!mInjectVSyncs) { ALOGE("VSync Injections not enabled"); return BAD_VALUE; @@ -3757,6 +3778,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case GET_ANIMATION_FRAME_STATS: case SET_POWER_MODE: case GET_HDR_CAPABILITIES: + case ENABLE_VSYNC_INJECTIONS: + case INJECT_VSYNC: { // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 9239538932..ba4f9ae688 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -338,6 +338,9 @@ private: // Called on the main thread in response to setActiveColorMode() void setActiveColorModeInternal(const sp& hw, android_color_mode_t colorMode); + // Called on the main thread in response to enableVSyncInjections() + void enableVSyncInjectionsInternal(bool enable); + // Returns whether the transaction actually modified any state bool handleMessageTransaction(); -- cgit v1.2.3-59-g8ed1b From a3d7bd39d130ec2e711692d045a435657c4bc0aa Mon Sep 17 00:00:00 2001 From: chaviw Date: Fri, 3 Nov 2017 09:41:53 -0700 Subject: Allow SurfaceFlinger to dump to proto SurfaceFlinger dump to proto was broken due to another CL. Test: "adb shell dumpsys SurfaceFlinger --proto" works correctly now Change-Id: I574e2a0b22764928e5ebdf1bd3f76bf20612f879 --- services/surfaceflinger/SurfaceFlinger.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 875bef1e67..a38e3b38d0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3490,11 +3490,6 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); - if (asProto) { - // Return early as SurfaceFlinger does not support dumping sections in proto format - return OK; - } - if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) { result.appendFormat("Permission Denial: " @@ -3514,6 +3509,13 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro bool dumpAll = true; size_t index = 0; size_t numArgs = args.size(); + + if (asProto) { + LayersProto layersProto = dumpProtoInfo(); + result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); + dumpAll = false; + } + if (numArgs) { if ((index < numArgs) && (args[index] == String16("--list"))) { @@ -3562,13 +3564,6 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro dumpWideColorInfo(result); dumpAll = false; } - - if ((index < numArgs) && (args[index] == String16("--proto"))) { - index++; - LayersProto layersProto = dumpProtoInfo(); - result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); - dumpAll = false; - } } if (dumpAll) { -- cgit v1.2.3-59-g8ed1b From 1e1a1282846318caa0bfe271500eb3ba24e9a513 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Wed, 1 Nov 2017 19:05:31 +0100 Subject: Add SurfaceFlinger tracing Bug: 64831661 Test: adb shell service call SurfaceFlinger 1025 i32 1 && adb shell service call SurfaceFlinger 1025 i32 0 Change-Id: Idf272715b52aee5d2d366fbd4a96b0afaaf2d0c7 --- services/surfaceflinger/Android.mk | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 23 ++++++ services/surfaceflinger/SurfaceFlinger.h | 3 + services/surfaceflinger/SurfaceTracing.cpp | 85 ++++++++++++++++++++++ services/surfaceflinger/SurfaceTracing.h | 50 +++++++++++++ services/surfaceflinger/layerproto/Android.bp | 1 + .../include/layerproto/LayerProtoHeader.h | 1 + .../surfaceflinger/layerproto/layerstrace.proto | 51 +++++++++++++ 8 files changed, 215 insertions(+) create mode 100644 services/surfaceflinger/SurfaceTracing.cpp create mode 100644 services/surfaceflinger/SurfaceTracing.h create mode 100644 services/surfaceflinger/layerproto/layerstrace.proto (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index d9bca04b0b..3f8ab3fc3f 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -21,6 +21,7 @@ LOCAL_SRC_FILES := \ MonitoredProducer.cpp \ SurfaceFlingerConsumer.cpp \ SurfaceInterceptor.cpp \ + SurfaceTracing.cpp \ Transform.cpp \ DisplayHardware/ComposerHal.cpp \ DisplayHardware/FramebufferSurface.cpp \ diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 875bef1e67..5be1e28437 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1520,6 +1520,7 @@ void SurfaceFlinger::handleMessageRefresh() { rebuildLayerStacks(); setUpHWComposer(); doDebugFlashRegions(); + doTracing("handleRefresh"); doComposition(); postComposition(refreshStartTime); @@ -1579,6 +1580,14 @@ void SurfaceFlinger::doDebugFlashRegions() } } +void SurfaceFlinger::doTracing(const char* where) { + ATRACE_CALL(); + ATRACE_NAME(where); + if (CC_UNLIKELY(mTracing.isEnabled())) { + mTracing.traceLayers(where, dumpProtoInfo()); + } +} + void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) { ATRACE_CALL(); @@ -4230,6 +4239,20 @@ status_t SurfaceFlinger::onTransact( reply->writeBool(hasWideColorDisplay); return NO_ERROR; } + case 1025: { // tracing + n = data.readInt32(); + if (n) { + ALOGV("LayerTracing enabled"); + mTracing.enable(); + doTracing("tracing.enable"); + reply->writeInt32(NO_ERROR); + } else { + ALOGV("LayerTracing disabled"); + status_t err = mTracing.disable(); + reply->writeInt32(err); + } + return NO_ERROR; + } } } return err; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 25ccb89dba..d0f4699b82 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -60,6 +60,7 @@ #include "LayerVector.h" #include "MessageQueue.h" #include "SurfaceInterceptor.h" +#include "SurfaceTracing.h" #include "StartPropertySetThread.h" #ifdef USE_HWC2 @@ -575,6 +576,7 @@ private: void setUpHWComposer(); void doComposition(); void doDebugFlashRegions(); + void doTracing(const char* where); void doDisplayComposition(const sp& displayDevice, const Region& dirtyRegion); // compose surfaces for display hw. this fails if using GL and the surface @@ -746,6 +748,7 @@ private: bool mPropagateBackpressure = true; #endif SurfaceInterceptor mInterceptor; + SurfaceTracing mTracing; bool mUseHwcVirtualDisplays = false; // Restrict layers to use two buffers in their bufferqueues. diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp new file mode 100644 index 0000000000..f8c466ea19 --- /dev/null +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#undef LOG_TAG +#define LOG_TAG "SurfaceTracing" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "SurfaceTracing.h" + +#include +#include +#include +#include + +namespace android { + +void SurfaceTracing::enable() { + if (mEnabled) { + return; + } + ATRACE_CALL(); + mEnabled = true; + std::lock_guard protoGuard(mTraceMutex); + + mTrace.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 | + LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L); +} + +status_t SurfaceTracing::disable() { + if (!mEnabled) { + return NO_ERROR; + } + ATRACE_CALL(); + std::lock_guard protoGuard(mTraceMutex); + mEnabled = false; + status_t err(writeProtoFileLocked()); + ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied"); + ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields"); + mTrace.Clear(); + return err; +} + +bool SurfaceTracing::isEnabled() { + return mEnabled; +} + +void SurfaceTracing::traceLayers(const char* where, LayersProto layers) { + std::lock_guard protoGuard(mTraceMutex); + + LayersTraceProto* entry = mTrace.add_entry(); + entry->set_elapsed_realtime_nanos(elapsedRealtimeNano()); + entry->set_where(where); + entry->mutable_layers()->Swap(&layers); +} + +status_t SurfaceTracing::writeProtoFileLocked() { + ATRACE_CALL(); + + if (!mTrace.IsInitialized()) { + return NOT_ENOUGH_DATA; + } + std::string output; + if (!mTrace.SerializeToString(&output)) { + return PERMISSION_DENIED; + } + if (!android::base::WriteStringToFile(output, mOutputFileName, true)) { + return PERMISSION_DENIED; + } + + return NO_ERROR; +} + +} // namespace android diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h new file mode 100644 index 0000000000..9b219890a1 --- /dev/null +++ b/services/surfaceflinger/SurfaceTracing.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include + +using namespace android::surfaceflinger; + +namespace android { + +/* + * SurfaceTracing records layer states during surface flinging. + */ +class SurfaceTracing { +public: + void enable(); + status_t disable(); + bool isEnabled(); + + void traceLayers(const char* where, LayersProto); + +private: + static constexpr auto DEFAULT_FILENAME = "/data/misc/trace/layerstrace.pb"; + + status_t writeProtoFileLocked(); + + bool mEnabled = false; + std::string mOutputFileName = DEFAULT_FILENAME; + std::mutex mTraceMutex; + LayersTraceFileProto mTrace; +}; + +} // namespace android diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp index 4c52bdfaa7..8eb218c96e 100644 --- a/services/surfaceflinger/layerproto/Android.bp +++ b/services/surfaceflinger/layerproto/Android.bp @@ -6,6 +6,7 @@ cc_library_shared { srcs: [ "LayerProtoParser.cpp", "layers.proto", + "layerstrace.proto", ], shared_libs: [ diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h index 054d4f2cbc..f560562c94 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h @@ -21,3 +21,4 @@ // This file should be included instead of directly including layer.b.h #pragma GCC system_header #include +#include diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto new file mode 100644 index 0000000000..bee17d2d86 --- /dev/null +++ b/services/surfaceflinger/layerproto/layerstrace.proto @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; + +import "frameworks/native/services/surfaceflinger/layerproto/layers.proto"; + +package android.surfaceflinger; + +/* represents a file full of surface flinger trace entries. + Encoded, it should start with 0x4c 0x59 0x52 0x54 0x52 0x41 0x43 0x45 (.LYRTRACE), such + that they can be easily identified. */ +message LayersTraceFileProto { + + /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L + (this is needed because enums have to be 32 bits and there's no nice way to put 64bit + constants into .proto files. */ + enum MagicNumber { + INVALID = 0; + MAGIC_NUMBER_L = 0x5452594c; /* LYRT (little-endian ASCII) */ + MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */ + } + + optional fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */ + repeated LayersTraceProto entry = 2; +} + +/* one window manager trace entry. */ +message LayersTraceProto { + /* required: elapsed realtime in nanos since boot of when this entry was logged */ + optional fixed64 elapsed_realtime_nanos = 1; + + /* where the trace originated */ + optional string where = 2; + + optional LayersProto layers = 3; +} -- cgit v1.2.3-59-g8ed1b From 0c69cad13dda09f1df1dbf23810b1c5b7f28ba08 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Mon, 21 Aug 2017 12:12:51 -0700 Subject: Refactor Layer/ColorLayer into siblings New class hierarchy should look like: Layer (abstract) / \ / \ Buffer Color Layer Layer Note: LayerBuffer is what previously was referred to by class Layer Test: Transaction_test.cpp/manual test Change-Id: I372a27d533e08371da37be811e4372404f7787bd --- services/surfaceflinger/Android.mk | 1 + services/surfaceflinger/BufferLayer.cpp | 911 ++++++++++++++++++++++++ services/surfaceflinger/BufferLayer.h | 184 +++++ services/surfaceflinger/ColorLayer.cpp | 5 +- services/surfaceflinger/ColorLayer.h | 16 +- services/surfaceflinger/Layer.cpp | 760 +------------------- services/surfaceflinger/Layer.h | 130 +--- services/surfaceflinger/SurfaceFlinger.cpp | 22 +- services/surfaceflinger/SurfaceFlinger.h | 5 +- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 21 +- 10 files changed, 1191 insertions(+), 864 deletions(-) create mode 100644 services/surfaceflinger/BufferLayer.cpp create mode 100644 services/surfaceflinger/BufferLayer.h (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 3f8ab3fc3f..7115ad62ea 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -14,6 +14,7 @@ LOCAL_SRC_FILES := \ FrameTracker.cpp \ GpuService.cpp \ Layer.cpp \ + BufferLayer.cpp \ ColorLayer.cpp \ LayerRejecter.cpp \ LayerVector.cpp \ diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp new file mode 100644 index 0000000000..ccb65f6df2 --- /dev/null +++ b/services/surfaceflinger/BufferLayer.cpp @@ -0,0 +1,911 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "BufferLayer" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "BufferLayer.h" +#include "Colorizer.h" +#include "DisplayDevice.h" +#include "LayerRejecter.h" +#include "clz.h" + +#include "RenderEngine/RenderEngine.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace android { + +BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags) + : Layer(flinger, client, name, w, h, flags), + mTextureName(-1U), + mFormat(PIXEL_FORMAT_NONE), + mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), + mBufferLatched(false), + mPreviousFrameNumber(0), + mUpdateTexImageFailed(false), + mRefreshPending(false) { +#ifdef USE_HWC2 + ALOGV("Creating Layer %s", name.string()); +#endif + + mFlinger->getRenderEngine().genTextures(1, &mTextureName); + mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); + + if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false; + + mCurrentState.requested = mCurrentState.active; + + // drawing state & current state are identical + mDrawingState = mCurrentState; +} + +BufferLayer::~BufferLayer() { + sp c(mClientRef.promote()); + if (c != 0) { + c->detachLayer(this); + } + + for (auto& point : mRemoteSyncPoints) { + point->setTransactionApplied(); + } + for (auto& point : mLocalSyncPoints) { + point->setFrameAvailable(); + } + mFlinger->deleteTextureAsync(mTextureName); + +#ifdef USE_HWC2 + if (!mHwcLayers.empty()) { + ALOGE("Found stale hardware composer layers when destroying " + "surface flinger layer %s", + mName.string()); + destroyAllHwcLayers(); + } +#endif +} + +bool BufferLayer::isProtected() const +{ + const sp& activeBuffer(mActiveBuffer); + return (activeBuffer != 0) && + (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); +} + +bool BufferLayer::isVisible() const { + return !(isHiddenByPolicy()) && getAlpha() > 0.0f && + (mActiveBuffer != NULL || mSidebandStream != NULL); +} + +bool BufferLayer::isFixedSize() const { + return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE; +} + +status_t BufferLayer::setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { + uint32_t const maxSurfaceDims = + min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); + + // never allow a surface larger than what our underlying GL implementation + // can handle. + if ((uint32_t(w) > maxSurfaceDims) || (uint32_t(h) > maxSurfaceDims)) { + ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); + return BAD_VALUE; + } + + mFormat = format; + + mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false; + mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; + mCurrentOpacity = getOpacityForFormat(format); + + mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); + mSurfaceFlingerConsumer->setDefaultBufferFormat(format); + mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); + + return NO_ERROR; +} + +static constexpr mat4 inverseOrientation(uint32_t transform) { + const mat4 flipH(-1,0,0,0, 0,1,0,0, 0,0,1,0, 1,0,0,1); + const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1); + const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1); + mat4 tr; + + if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) { + tr = tr * rot90; + } + if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { + tr = tr * flipH; + } + if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { + tr = tr * flipV; + } + return inverse(tr); +} + +/* + * onDraw will draw the current layer onto the presentable buffer + */ +void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, + bool useIdentityTransform) const { + ATRACE_CALL(); + + if (CC_UNLIKELY(mActiveBuffer == 0)) { + // the texture has not been created yet, this Layer has + // in fact never been drawn into. This happens frequently with + // SurfaceView because the WindowManager can't know when the client + // has drawn the first time. + + // If there is nothing under us, we paint the screen in black, otherwise + // we just skip this update. + + // figure out if there is something below us + Region under; + bool finished = false; + mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) { + if (finished || layer == static_cast(this)) { + finished = true; + return; + } + under.orSelf(renderArea.getTransform().transform(layer->visibleRegion)); + }); + // if not everything below us is covered, we plug the holes! + Region holes(clip.subtract(under)); + if (!holes.isEmpty()) { + clearWithOpenGL(renderArea, 0, 0, 0, 1); + } + return; + } + + // Bind the current buffer to the GL texture, and wait for it to be + // ready for us to draw into. + status_t err = mSurfaceFlingerConsumer->bindTextureImage(); + if (err != NO_ERROR) { + ALOGW("onDraw: bindTextureImage failed (err=%d)", err); + // Go ahead and draw the buffer anyway; no matter what we do the screen + // is probably going to have something visibly wrong. + } + + bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure()); + + RenderEngine& engine(mFlinger->getRenderEngine()); + + if (!blackOutLayer) { + // TODO: we could be more subtle with isFixedSize() + const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize(); + + // Query the texture matrix given our current filtering mode. + float textureMatrix[16]; + mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering); + mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix); + + if (getTransformToDisplayInverse()) { + /* + * the code below applies the primary display's inverse transform to + * the texture transform + */ + uint32_t transform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + mat4 tr = inverseOrientation(transform); + + /** + * TODO(b/36727915): This is basically a hack. + * + * Ensure that regardless of the parent transformation, + * this buffer is always transformed from native display + * orientation to display orientation. For example, in the case + * of a camera where the buffer remains in native orientation, + * we want the pixels to always be upright. + */ + sp p = mDrawingParent.promote(); + if (p != nullptr) { + const auto parentTransform = p->getTransform(); + tr = tr * inverseOrientation(parentTransform.getOrientation()); + } + + // and finally apply it to the original texture matrix + const mat4 texTransform(mat4(static_cast(textureMatrix)) * tr); + memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix)); + } + + // Set things up for texturing. + mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight()); + mTexture.setFiltering(useFiltering); + mTexture.setMatrix(textureMatrix); + + engine.setupLayerTexturing(mTexture); + } else { + engine.setupLayerBlackedOut(); + } + drawWithOpenGL(renderArea, useIdentityTransform); + engine.disableTexturing(); +} + +bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { + if (mBufferLatched) { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); + } + mRefreshPending = false; + return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; +} + +#ifdef USE_HWC2 +void BufferLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { + if (!mSurfaceFlingerConsumer->releasePendingBuffer()) { + return; + } + + auto releaseFenceTime = + std::make_shared(mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); + mReleaseTimeline.updateSignalTimes(); + mReleaseTimeline.push(releaseFenceTime); + + Mutex::Autolock lock(mFrameEventHistoryMutex); + if (mPreviousFrameNumber != 0) { + mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime, + std::move(releaseFenceTime)); + } +} +#endif + +Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) { + ATRACE_CALL(); + + if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { + // mSidebandStreamChanged was true + mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream(); + if (mSidebandStream != NULL) { + setTransactionFlags(eTransactionNeeded); + mFlinger->setTransactionFlags(eTraversalNeeded); + } + recomputeVisibleRegions = true; + + const State& s(getDrawingState()); + return getTransform().transform(Region(Rect(s.active.w, s.active.h))); + } + + Region outDirtyRegion; + if (mQueuedFrames <= 0 && !mAutoRefresh) { + return outDirtyRegion; + } + + // if we've already called updateTexImage() without going through + // a composition step, we have to skip this layer at this point + // because we cannot call updateTeximage() without a corresponding + // compositionComplete() call. + // we'll trigger an update in onPreComposition(). + if (mRefreshPending) { + return outDirtyRegion; + } + + // If the head buffer's acquire fence hasn't signaled yet, return and + // try again later + if (!headFenceHasSignaled()) { + mFlinger->signalLayerUpdate(); + return outDirtyRegion; + } + + // Capture the old state of the layer for comparisons later + const State& s(getDrawingState()); + const bool oldOpacity = isOpaque(s); + sp oldActiveBuffer = mActiveBuffer; + + if (!allTransactionsSignaled()) { + mFlinger->signalLayerUpdate(); + return outDirtyRegion; + } + + // This boolean is used to make sure that SurfaceFlinger's shadow copy + // of the buffer queue isn't modified when the buffer queue is returning + // BufferItem's that weren't actually queued. This can happen in shared + // buffer mode. + bool queuedBuffer = false; + LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, + getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, + mFreezeGeometryUpdates); + status_t updateResult = + mSurfaceFlingerConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync, &mAutoRefresh, + &queuedBuffer, mLastFrameNumberReceived); + if (updateResult == BufferQueue::PRESENT_LATER) { + // Producer doesn't want buffer to be displayed yet. Signal a + // layer update so we check again at the next opportunity. + mFlinger->signalLayerUpdate(); + return outDirtyRegion; + } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) { + // If the buffer has been rejected, remove it from the shadow queue + // and return early + if (queuedBuffer) { + Mutex::Autolock lock(mQueueItemLock); + mQueueItems.removeAt(0); + android_atomic_dec(&mQueuedFrames); + } + return outDirtyRegion; + } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) { + // This can occur if something goes wrong when trying to create the + // EGLImage for this buffer. If this happens, the buffer has already + // been released, so we need to clean up the queue and bug out + // early. + if (queuedBuffer) { + Mutex::Autolock lock(mQueueItemLock); + mQueueItems.clear(); + android_atomic_and(0, &mQueuedFrames); + } + + // Once we have hit this state, the shadow queue may no longer + // correctly reflect the incoming BufferQueue's contents, so even if + // updateTexImage starts working, the only safe course of action is + // to continue to ignore updates. + mUpdateTexImageFailed = true; + + return outDirtyRegion; + } + + if (queuedBuffer) { + // Autolock scope + auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); + + Mutex::Autolock lock(mQueueItemLock); + + // Remove any stale buffers that have been dropped during + // updateTexImage + while (mQueueItems[0].mFrameNumber != currentFrameNumber) { + mQueueItems.removeAt(0); + android_atomic_dec(&mQueuedFrames); + } + + mQueueItems.removeAt(0); + } + + // Decrement the queued-frames count. Signal another event if we + // have more frames pending. + if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) || mAutoRefresh) { + mFlinger->signalLayerUpdate(); + } + + // update the active buffer + mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(&mActiveBufferSlot); + if (mActiveBuffer == NULL) { + // this can only happen if the very first buffer was rejected. + return outDirtyRegion; + } + + mBufferLatched = true; + mPreviousFrameNumber = mCurrentFrameNumber; + mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); + + { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); +#ifndef USE_HWC2 + auto releaseFenceTime = + std::make_shared(mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); + mReleaseTimeline.updateSignalTimes(); + mReleaseTimeline.push(releaseFenceTime); + if (mPreviousFrameNumber != 0) { + mFrameEventHistory.addRelease(mPreviousFrameNumber, latchTime, + std::move(releaseFenceTime)); + } +#endif + } + + mRefreshPending = true; + mFrameLatencyNeeded = true; + if (oldActiveBuffer == NULL) { + // the first time we receive a buffer, we need to trigger a + // geometry invalidation. + recomputeVisibleRegions = true; + } + + setDataSpace(mSurfaceFlingerConsumer->getCurrentDataSpace()); + + Rect crop(mSurfaceFlingerConsumer->getCurrentCrop()); + const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform()); + const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode()); + if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || + (scalingMode != mCurrentScalingMode)) { + mCurrentCrop = crop; + mCurrentTransform = transform; + mCurrentScalingMode = scalingMode; + recomputeVisibleRegions = true; + } + + if (oldActiveBuffer != NULL) { + uint32_t bufWidth = mActiveBuffer->getWidth(); + uint32_t bufHeight = mActiveBuffer->getHeight(); + if (bufWidth != uint32_t(oldActiveBuffer->width) || + bufHeight != uint32_t(oldActiveBuffer->height)) { + recomputeVisibleRegions = true; + } + } + + mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); + if (oldOpacity != isOpaque(s)) { + recomputeVisibleRegions = true; + } + + // Remove any sync points corresponding to the buffer which was just + // latched + { + Mutex::Autolock lock(mLocalSyncPointMutex); + auto point = mLocalSyncPoints.begin(); + while (point != mLocalSyncPoints.end()) { + if (!(*point)->frameIsAvailable() || !(*point)->transactionIsApplied()) { + // This sync point must have been added since we started + // latching. Don't drop it yet. + ++point; + continue; + } + + if ((*point)->getFrameNumber() <= mCurrentFrameNumber) { + point = mLocalSyncPoints.erase(point); + } else { + ++point; + } + } + } + + // FIXME: postedRegion should be dirty & bounds + Region dirtyRegion(Rect(s.active.w, s.active.h)); + + // transform the dirty region to window-manager space + outDirtyRegion = (getTransform().transform(dirtyRegion)); + + return outDirtyRegion; +} + +#ifdef USE_HWC2 +void BufferLayer::setPerFrameData(const sp& displayDevice) { + // Apply this display's projection's viewport to the visible region + // before giving it to the HWC HAL. + const Transform& tr = displayDevice->getTransform(); + const auto& viewport = displayDevice->getViewport(); + Region visible = tr.transform(visibleRegion.intersect(viewport)); + auto hwcId = displayDevice->getHwcDisplayId(); + auto& hwcInfo = mHwcLayers[hwcId]; + auto& hwcLayer = hwcInfo.layer; + auto error = hwcLayer->setVisibleRegion(visible); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast(error)); + visible.dump(LOG_TAG); + } + + error = hwcLayer->setSurfaceDamage(surfaceDamageRegion); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast(error)); + surfaceDamageRegion.dump(LOG_TAG); + } + + // Sideband layers + if (mSidebandStream.get()) { + setCompositionType(hwcId, HWC2::Composition::Sideband); + ALOGV("[%s] Requesting Sideband composition", mName.string()); + error = hwcLayer->setSidebandStream(mSidebandStream->handle()); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), + mSidebandStream->handle(), to_string(error).c_str(), static_cast(error)); + } + return; + } + + // Client layers + if (hwcInfo.forceClientComposition || + (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) { + ALOGV("[%s] Requesting Client composition", mName.string()); + setCompositionType(hwcId, HWC2::Composition::Client); + return; + } + + // SolidColor layers + if (mActiveBuffer == nullptr) { + setCompositionType(hwcId, HWC2::Composition::SolidColor); + + // For now, we only support black for DimLayer + error = hwcLayer->setColor({0, 0, 0, 255}); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), + static_cast(error)); + } + + // Clear out the transform, because it doesn't make sense absent a + // source buffer + error = hwcLayer->setTransform(HWC2::Transform::None); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast(error)); + } + + return; + } + + // Device or Cursor layers + if (mPotentialCursor) { + ALOGV("[%s] Requesting Cursor composition", mName.string()); + setCompositionType(hwcId, HWC2::Composition::Cursor); + } else { + ALOGV("[%s] Requesting Device composition", mName.string()); + setCompositionType(hwcId, HWC2::Composition::Device); + } + + ALOGV("setPerFrameData: dataspace = %d", mCurrentState.dataSpace); + error = hwcLayer->setDataspace(mCurrentState.dataSpace); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentState.dataSpace, + to_string(error).c_str(), static_cast(error)); + } + + uint32_t hwcSlot = 0; + sp hwcBuffer; + hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer); + + auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence(); + error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), mActiveBuffer->handle, + to_string(error).c_str(), static_cast(error)); + } +} + +#else +void BufferLayer::setPerFrameData(const sp& hw, + HWComposer::HWCLayerInterface& layer) { + // we have to set the visible region on every frame because + // we currently free it during onLayerDisplayed(), which is called + // after HWComposer::commit() -- every frame. + // Apply this display's projection's viewport to the visible region + // before giving it to the HWC HAL. + const Transform& tr = hw->getTransform(); + Region visible = tr.transform(visibleRegion.intersect(hw->getViewport())); + layer.setVisibleRegionScreen(visible); + layer.setSurfaceDamage(surfaceDamageRegion); + mIsGlesComposition = (layer.getCompositionType() == HWC_FRAMEBUFFER); + + if (mSidebandStream.get()) { + layer.setSidebandStream(mSidebandStream); + } else { + // NOTE: buffer can be NULL if the client never drew into this + // layer yet, or if we ran out of memory + layer.setBuffer(mActiveBuffer); + } +} +#endif + +bool BufferLayer::isOpaque(const Layer::State& s) const +{ + // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the + // layer's opaque flag. + if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) { + return false; + } + + // if the layer has the opaque flag, then we're always opaque, + // otherwise we use the current buffer's format. + return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity; +} + +void BufferLayer::onFirstRef() { + // Creates a custom BufferQueue for SurfaceFlingerConsumer to use + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer, true); + mProducer = new MonitoredProducer(producer, mFlinger, this); + mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this); + mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); + mSurfaceFlingerConsumer->setContentsChangedListener(this); + mSurfaceFlingerConsumer->setName(mName); + + if (mFlinger->isLayerTripleBufferingDisabled()) { + mProducer->setMaxDequeuedBufferCount(2); + } + + const sp hw(mFlinger->getDefaultDisplayDevice()); + updateTransformHint(hw); +} + +// --------------------------------------------------------------------------- +// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener +// --------------------------------------------------------------------------- + +void BufferLayer::onFrameAvailable(const BufferItem& item) { + // Add this buffer from our internal queue tracker + { // Autolock scope + Mutex::Autolock lock(mQueueItemLock); + mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), + item.mGraphicBuffer->getHeight(), + item.mFrameNumber); + // Reset the frame number tracker when we receive the first buffer after + // a frame number reset + if (item.mFrameNumber == 1) { + mLastFrameNumberReceived = 0; + } + + // Ensure that callbacks are handled in order + while (item.mFrameNumber != mLastFrameNumberReceived + 1) { + status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); + if (result != NO_ERROR) { + ALOGE("[%s] Timed out waiting on callback", mName.string()); + } + } + + mQueueItems.push_back(item); + android_atomic_inc(&mQueuedFrames); + + // Wake up any pending callbacks + mLastFrameNumberReceived = item.mFrameNumber; + mQueueItemCondition.broadcast(); + } + + mFlinger->signalLayerUpdate(); +} + +void BufferLayer::onFrameReplaced(const BufferItem& item) { + { // Autolock scope + Mutex::Autolock lock(mQueueItemLock); + + // Ensure that callbacks are handled in order + while (item.mFrameNumber != mLastFrameNumberReceived + 1) { + status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); + if (result != NO_ERROR) { + ALOGE("[%s] Timed out waiting on callback", mName.string()); + } + } + + if (mQueueItems.empty()) { + ALOGE("Can't replace a frame on an empty queue"); + return; + } + mQueueItems.editItemAt(mQueueItems.size() - 1) = item; + + // Wake up any pending callbacks + mLastFrameNumberReceived = item.mFrameNumber; + mQueueItemCondition.broadcast(); + } +} + +void BufferLayer::onSidebandStreamChanged() { + if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { + // mSidebandStreamChanged was false + mFlinger->signalLayerUpdate(); + } +} + +bool BufferLayer::needsFiltering(const RenderArea& renderArea) const { + return mNeedsFiltering || renderArea.needsFiltering(); +} + +// As documented in libhardware header, formats in the range +// 0x100 - 0x1FF are specific to the HAL implementation, and +// are known to have no alpha channel +// TODO: move definition for device-specific range into +// hardware.h, instead of using hard-coded values here. +#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF) + +bool BufferLayer::getOpacityForFormat(uint32_t format) { + if (HARDWARE_IS_DEVICE_FORMAT(format)) { + return true; + } + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBA_FP16: + case HAL_PIXEL_FORMAT_RGBA_1010102: + return false; + } + // in all other case, we have no blending (also for unknown formats) + return true; +} + +void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, + bool useIdentityTransform) const { + const State& s(getDrawingState()); + + computeGeometry(renderArea, mMesh, useIdentityTransform); + + /* + * NOTE: the way we compute the texture coordinates here produces + * different results than when we take the HWC path -- in the later case + * the "source crop" is rounded to texel boundaries. + * This can produce significantly different results when the texture + * is scaled by a large amount. + * + * The GL code below is more logical (imho), and the difference with + * HWC is due to a limitation of the HWC API to integers -- a question + * is suspend is whether we should ignore this problem or revert to + * GL composition when a buffer scaling is applied (maybe with some + * minimal value)? Or, we could make GL behave like HWC -- but this feel + * like more of a hack. + */ + Rect win(computeBounds()); + + Transform t = getTransform(); + if (!s.finalCrop.isEmpty()) { + win = t.transform(win); + if (!win.intersect(s.finalCrop, &win)) { + win.clear(); + } + win = t.inverse().transform(win); + if (!win.intersect(computeBounds(), &win)) { + win.clear(); + } + } + + float left = float(win.left) / float(s.active.w); + float top = float(win.top) / float(s.active.h); + float right = float(win.right) / float(s.active.w); + float bottom = float(win.bottom) / float(s.active.h); + + // TODO: we probably want to generate the texture coords with the mesh + // here we assume that we only have 4 vertices + Mesh::VertexArray texCoords(mMesh.getTexCoordArray()); + texCoords[0] = vec2(left, 1.0f - top); + texCoords[1] = vec2(left, 1.0f - bottom); + texCoords[2] = vec2(right, 1.0f - bottom); + texCoords[3] = vec2(right, 1.0f - top); + + RenderEngine& engine(mFlinger->getRenderEngine()); + engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */, + getColor()); +#ifdef USE_HWC2 + engine.setSourceDataSpace(mCurrentState.dataSpace); +#endif + engine.drawMesh(mMesh); + engine.disableBlending(); +} + +uint32_t BufferLayer::getProducerStickyTransform() const { + int producerStickyTransform = 0; + int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform); + if (ret != OK) { + ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__, + strerror(-ret), ret); + return 0; + } + return static_cast(producerStickyTransform); +} + +bool BufferLayer::latchUnsignaledBuffers() { + static bool propertyLoaded = false; + static bool latch = false; + static std::mutex mutex; + std::lock_guard lock(mutex); + if (!propertyLoaded) { + char value[PROPERTY_VALUE_MAX] = {}; + property_get("debug.sf.latch_unsignaled", value, "0"); + latch = atoi(value); + propertyLoaded = true; + } + return latch; +} + +uint64_t BufferLayer::getHeadFrameNumber() const { + Mutex::Autolock lock(mQueueItemLock); + if (!mQueueItems.empty()) { + return mQueueItems[0].mFrameNumber; + } else { + return mCurrentFrameNumber; + } +} + +bool BufferLayer::headFenceHasSignaled() const { +#ifdef USE_HWC2 + if (latchUnsignaledBuffers()) { + return true; + } + + Mutex::Autolock lock(mQueueItemLock); + if (mQueueItems.empty()) { + return true; + } + if (mQueueItems[0].mIsDroppable) { + // Even though this buffer's fence may not have signaled yet, it could + // be replaced by another buffer before it has a chance to, which means + // that it's possible to get into a situation where a buffer is never + // able to be latched. To avoid this, grab this buffer anyway. + return true; + } + return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; +#else + return true; +#endif +} + +uint32_t BufferLayer::getEffectiveScalingMode() const { + if (mOverrideScalingMode >= 0) { + return mOverrideScalingMode; + } + return mCurrentScalingMode; +} + +// ---------------------------------------------------------------------------- +// transaction +// ---------------------------------------------------------------------------- + +void BufferLayer::notifyAvailableFrames() { + auto headFrameNumber = getHeadFrameNumber(); + bool headFenceSignaled = headFenceHasSignaled(); + Mutex::Autolock lock(mLocalSyncPointMutex); + for (auto& point : mLocalSyncPoints) { + if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) { + point->setFrameAvailable(); + } + } +} + +sp BufferLayer::getProducer() const { + return mProducer; +} + +// --------------------------------------------------------------------------- +// h/w composer set-up +// --------------------------------------------------------------------------- + +bool BufferLayer::allTransactionsSignaled() { + auto headFrameNumber = getHeadFrameNumber(); + bool matchingFramesFound = false; + bool allTransactionsApplied = true; + Mutex::Autolock lock(mLocalSyncPointMutex); + + for (auto& point : mLocalSyncPoints) { + if (point->getFrameNumber() > headFrameNumber) { + break; + } + matchingFramesFound = true; + + if (!point->frameIsAvailable()) { + // We haven't notified the remote layer that the frame for + // this point is available yet. Notify it now, and then + // abort this attempt to latch. + point->setFrameAvailable(); + allTransactionsApplied = false; + break; + } + + allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied(); + } + return !matchingFramesFound || allTransactionsApplied; +} + +} // namespace android + +#if defined(__gl_h_) +#error "don't include gl/gl.h in this file" +#endif + +#if defined(__gl2_h_) +#error "don't include gl2/gl2.h in this file" +#endif diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h new file mode 100644 index 0000000000..b245f2976e --- /dev/null +++ b/services/surfaceflinger/BufferLayer.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Layer.h" +#include "Client.h" +#include "DisplayHardware/HWComposer.h" +#include "DisplayHardware/HWComposerBufferCache.h" +#include "FrameTracker.h" +#include "LayerVector.h" +#include "MonitoredProducer.h" +#include "RenderEngine/Mesh.h" +#include "RenderEngine/Texture.h" +#include "SurfaceFlinger.h" +#include "SurfaceFlingerConsumer.h" +#include "Transform.h" + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace android { + +/* + * A new BufferQueue and a new SurfaceFlingerConsumer are created when the + * BufferLayer is first referenced. + * + * This also implements onFrameAvailable(), which notifies SurfaceFlinger + * that new data has arrived. + */ +class BufferLayer : public Layer, public SurfaceFlingerConsumer::ContentsChangedListener { +public: + BufferLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, + uint32_t h, uint32_t flags); + + ~BufferLayer() override; + + // ----------------------------------------------------------------------- + // Overriden from Layer + // ----------------------------------------------------------------------- + + /* + * getTypeId - Provide unique string for each class type in the Layer + * hierarchy + */ + const char* getTypeId() const override { return "BufferLayer"; } + + /* + * isProtected - true if the layer may contain protected content in the + * GRALLOC_USAGE_PROTECTED sense. + */ + bool isProtected() const; + + /* + * isVisible - true if this layer is visible, false otherwise + */ + bool isVisible() const override; + + /* + * isFixedSize - true if content has a fixed size + */ + bool isFixedSize() const override; + + // the this layer's size and format + status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); + + /* + * onDraw - draws the surface. + */ + void onDraw(const RenderArea& renderArea, const Region& clip, + bool useIdentityTransform) const override; + + bool onPreComposition(nsecs_t refreshStartTime) override; + +#ifdef USE_HWC2 + // If a buffer was replaced this frame, release the former buffer + void releasePendingBuffer(nsecs_t dequeueReadyTime); +#endif + + /* + * latchBuffer - called each time the screen is redrawn and returns whether + * the visible regions need to be recomputed (this is a fairly heavy + * operation, so this should be set only if needed). Typically this is used + * to figure out if the content or size of a surface has changed. + */ + Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + bool isBufferLatched() const override { return mRefreshPending; } + +#ifdef USE_HWC2 + void setPerFrameData(const sp& displayDevice); +#else + void setPerFrameData(const sp& hw, HWComposer::HWCLayerInterface& layer); +#endif + bool isOpaque(const Layer::State& s) const override; + +private: + void onFirstRef() override; + + // Interface implementation for + // SurfaceFlingerConsumer::ContentsChangedListener + void onFrameAvailable(const BufferItem& item) override; + void onFrameReplaced(const BufferItem& item) override; + void onSidebandStreamChanged() override; + + // needsLinearFiltering - true if this surface's state requires filtering + bool needsFiltering(const RenderArea& renderArea) const; + + static bool getOpacityForFormat(uint32_t format); + + // drawing + void drawWithOpenGL(const RenderArea& renderArea, + bool useIdentityTransform) const; + + // Temporary - Used only for LEGACY camera mode. + uint32_t getProducerStickyTransform() const; + + // Loads the corresponding system property once per process + static bool latchUnsignaledBuffers(); + + uint64_t getHeadFrameNumber() const; + bool headFenceHasSignaled() const; + + // Returns the current scaling mode, unless mOverrideScalingMode + // is set, in which case, it returns mOverrideScalingMode + uint32_t getEffectiveScalingMode() const override; + +public: + void notifyAvailableFrames() override; + + PixelFormat getPixelFormat() const override { return mFormat; } + sp getProducer() const; + +private: + // Check all of the local sync points to ensure that all transactions + // which need to have been applied prior to the frame which is about to + // be latched have signaled + bool allTransactionsSignaled(); + sp mProducer; + + // constants + uint32_t mTextureName; // from GLES + PixelFormat mFormat; + + // main thread + uint32_t mCurrentScalingMode; + bool mBufferLatched = false; // TODO: Use mActiveBuffer? + uint64_t mPreviousFrameNumber; // Only accessed on the main thread. + // The texture used to draw the layer in GLES composition mode + mutable Texture mTexture; + + bool mUpdateTexImageFailed; // This is only accessed on the main thread. + bool mRefreshPending; +}; + +} // namespace android diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 32526dd29b..72fdaaa654 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -37,7 +37,10 @@ namespace android { ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags) - : Layer(flinger, client, name, w, h, flags) { + : Layer(flinger, client, name, w, h, flags) { + + // drawing state & current state are identical + mDrawingState = mCurrentState; } void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index cdf3eca60a..c68ad023e1 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -26,8 +26,7 @@ namespace android { -class ColorLayer : public Layer -{ +class ColorLayer : public Layer { public: ColorLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags); @@ -36,10 +35,19 @@ public: virtual const char* getTypeId() const { return "ColorLayer"; } virtual void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const; + bool isVisible() const override; virtual bool isOpaque(const Layer::State&) const { return false; } - virtual bool isSecure() const { return false; } virtual bool isFixedSize() const { return true; } - virtual bool isVisible() const; + + void notifyAvailableFrames() override {} + PixelFormat getPixelFormat() const override { return PIXEL_FORMAT_NONE; } + uint32_t getEffectiveScalingMode() const override { return 0; } +#ifdef USE_HWC2 + void releasePendingBuffer(nsecs_t) override {} +#endif + Region latchBuffer(bool&, nsecs_t) override { return Region(); } + bool isBufferLatched() const override { return false; } + bool onPreComposition(nsecs_t) override { return true; } }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 0525607c35..763488c8f5 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -62,19 +62,16 @@ namespace android { -// --------------------------------------------------------------------------- - int32_t Layer::sSequence = 1; Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags) - : contentDirty(false), + : contentDirty(false), sequence(uint32_t(android_atomic_inc(&sSequence))), mFlinger(flinger), - mTextureName(UINT32_MAX), + mSurfaceFlingerConsumer(NULL), mPremultipliedAlpha(true), - mName("unnamed"), - mFormat(PIXEL_FORMAT_NONE), + mName(name), mTransactionFlags(0), mPendingStateMutex(), mPendingStates(), @@ -82,13 +79,9 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, mSidebandStreamChanged(false), mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), mCurrentTransform(0), - mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mOverrideScalingMode(-1), mCurrentOpacity(true), - mBufferLatched(false), mCurrentFrameNumber(0), - mPreviousFrameNumber(0), - mRefreshPending(false), mFrameLatencyNeeded(false), mFiltering(false), mNeedsFiltering(false), @@ -97,24 +90,17 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, mIsGlesComposition(false), #endif mProtectedByApp(false), - mHasSurface(false), mClientRef(client), mPotentialCursor(false), mQueueItemLock(), mQueueItemCondition(), mQueueItems(), mLastFrameNumberReceived(0), - mUpdateTexImageFailed(false), mAutoRefresh(false), mFreezeGeometryUpdates(false) { -#ifdef USE_HWC2 - ALOGV("Creating Layer %s", name.string()); -#endif mCurrentCrop.makeInvalid(); - mFlinger->getRenderEngine().genTextures(1, &mTextureName); - mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); uint32_t layerFlags = 0; if (flags & ISurfaceComposerClient::eHidden) @@ -124,14 +110,12 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, if (flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure; - if (flags & ISurfaceComposerClient::eNonPremultiplied) - mPremultipliedAlpha = false; - mName = name; mTransactionName = String8("TX - ") + mName; mCurrentState.active.w = w; mCurrentState.active.h = h; + mCurrentState.flags = layerFlags; mCurrentState.active.transform.set(0, 0); mCurrentState.crop.makeInvalid(); mCurrentState.finalCrop.makeInvalid(); @@ -140,7 +124,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, mCurrentState.z = 0; mCurrentState.color.a = 1.0f; mCurrentState.layerStack = 0; - mCurrentState.flags = layerFlags; mCurrentState.sequence = 0; mCurrentState.requested = mCurrentState.active; mCurrentState.dataSpace = HAL_DATASPACE_UNKNOWN; @@ -166,46 +149,10 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, } void Layer::onFirstRef() { - // Creates a custom BufferQueue for SurfaceFlingerConsumer to use - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer, true); - mProducer = new MonitoredProducer(producer, mFlinger, this); - mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this); - mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); - mSurfaceFlingerConsumer->setContentsChangedListener(this); - mSurfaceFlingerConsumer->setName(mName); - - if (mFlinger->isLayerTripleBufferingDisabled()) { - mProducer->setMaxDequeuedBufferCount(2); - } - - const sp hw(mFlinger->getDefaultDisplayDevice()); - updateTransformHint(hw); } Layer::~Layer() { - sp c(mClientRef.promote()); - if (c != 0) { - c->detachLayer(this); - } - - for (auto& point : mRemoteSyncPoints) { - point->setTransactionApplied(); - } - for (auto& point : mLocalSyncPoints) { - point->setFrameAvailable(); - } - mFlinger->deleteTextureAsync(mTextureName); mFrameTracker.logAndResetStats(mName); - -#ifdef USE_HWC2 - if (!mHwcLayers.empty()) { - ALOGE("Found stale hardware composer layers when destroying " - "surface flinger layer %s", mName.string()); - destroyAllHwcLayers(); - } -#endif } // --------------------------------------------------------------------------- @@ -217,7 +164,9 @@ void Layer::onLayerDisplayed(const sp& releaseFence) { if (mHwcLayers.empty()) { return; } - mSurfaceFlingerConsumer->setReleaseFence(releaseFence); + if (mSurfaceFlingerConsumer) { + mSurfaceFlingerConsumer->setReleaseFence(releaseFence); + } } #else void Layer::onLayerDisplayed(const sp& /* hw */, @@ -229,70 +178,6 @@ void Layer::onLayerDisplayed(const sp& /* hw */, } #endif -void Layer::onFrameAvailable(const BufferItem& item) { - // Add this buffer from our internal queue tracker - { // Autolock scope - Mutex::Autolock lock(mQueueItemLock); - mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), - item.mGraphicBuffer->getHeight(), item.mFrameNumber); - // Reset the frame number tracker when we receive the first buffer after - // a frame number reset - if (item.mFrameNumber == 1) { - mLastFrameNumberReceived = 0; - } - - // Ensure that callbacks are handled in order - while (item.mFrameNumber != mLastFrameNumberReceived + 1) { - status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, - ms2ns(500)); - if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); - } - } - - mQueueItems.push_back(item); - android_atomic_inc(&mQueuedFrames); - - // Wake up any pending callbacks - mLastFrameNumberReceived = item.mFrameNumber; - mQueueItemCondition.broadcast(); - } - - mFlinger->signalLayerUpdate(); -} - -void Layer::onFrameReplaced(const BufferItem& item) { - { // Autolock scope - Mutex::Autolock lock(mQueueItemLock); - - // Ensure that callbacks are handled in order - while (item.mFrameNumber != mLastFrameNumberReceived + 1) { - status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, - ms2ns(500)); - if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); - } - } - - if (mQueueItems.empty()) { - ALOGE("Can't replace a frame on an empty queue"); - return; - } - mQueueItems.editItemAt(mQueueItems.size() - 1) = item; - - // Wake up any pending callbacks - mLastFrameNumberReceived = item.mFrameNumber; - mQueueItemCondition.broadcast(); - } -} - -void Layer::onSidebandStreamChanged() { - if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { - // mSidebandStreamChanged was false - mFlinger->signalLayerUpdate(); - } -} - void Layer::onRemovedFromCurrentState() { // the layer is removed from SF mCurrentState to mLayersPendingRemoval @@ -313,7 +198,9 @@ void Layer::onRemovedFromCurrentState() { void Layer::onRemoved() { // the layer is removed from SF mLayersPendingRemoval - mSurfaceFlingerConsumer->abandon(); + if (mSurfaceFlingerConsumer) { + mSurfaceFlingerConsumer->abandon(); + } #ifdef USE_HWC2 destroyAllHwcLayers(); #endif @@ -335,47 +222,11 @@ bool Layer::getPremultipledAlpha() const { return mPremultipliedAlpha; } -status_t Layer::setBuffers( uint32_t w, uint32_t h, - PixelFormat format, uint32_t flags) -{ - uint32_t const maxSurfaceDims = min( - mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); - - // never allow a surface larger than what our underlying GL implementation - // can handle. - if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) { - ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); - return BAD_VALUE; - } - - mFormat = format; - - mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false; - mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; - mCurrentOpacity = getOpacityForFormat(format); - - mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); - mSurfaceFlingerConsumer->setDefaultBufferFormat(format); - mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); - - return NO_ERROR; -} - sp Layer::getHandle() { Mutex::Autolock _l(mLock); - - LOG_ALWAYS_FATAL_IF(mHasSurface, - "Layer::getHandle() has already been called"); - - mHasSurface = true; - return new Handle(mFlinger, this); } -sp Layer::getProducer() const { - return mProducer; -} - // --------------------------------------------------------------------------- // h/w composer set-up // --------------------------------------------------------------------------- @@ -1077,125 +928,6 @@ void Layer::draw(const RenderArea& renderArea) const { onDraw(renderArea, Region(renderArea.getBounds()), false); } -static constexpr mat4 inverseOrientation(uint32_t transform) { - const mat4 flipH(-1,0,0,0, 0,1,0,0, 0,0,1,0, 1,0,0,1); - const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1); - const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1); - mat4 tr; - - if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) { - tr = tr * rot90; - } - if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { - tr = tr * flipH; - } - if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { - tr = tr * flipV; - } - return inverse(tr); -} - -/* - * onDraw will draw the current layer onto the presentable buffer - */ -void Layer::onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const -{ - ATRACE_CALL(); - - if (CC_UNLIKELY(mActiveBuffer == 0)) { - // the texture has not been created yet, this Layer has - // in fact never been drawn into. This happens frequently with - // SurfaceView because the WindowManager can't know when the client - // has drawn the first time. - - // If there is nothing under us, we paint the screen in black, otherwise - // we just skip this update. - - // figure out if there is something below us - Region under; - bool finished = false; - mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) { - if (finished || layer == static_cast(this)) { - finished = true; - return; - } - under.orSelf(renderArea.getTransform().transform(layer->visibleRegion)); - }); - // if not everything below us is covered, we plug the holes! - Region holes(clip.subtract(under)); - if (!holes.isEmpty()) { - clearWithOpenGL(renderArea, 0, 0, 0, 1); - } - return; - } - - // Bind the current buffer to the GL texture, and wait for it to be - // ready for us to draw into. - status_t err = mSurfaceFlingerConsumer->bindTextureImage(); - if (err != NO_ERROR) { - ALOGW("onDraw: bindTextureImage failed (err=%d)", err); - // Go ahead and draw the buffer anyway; no matter what we do the screen - // is probably going to have something visibly wrong. - } - - bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure()); - - RenderEngine& engine(mFlinger->getRenderEngine()); - - if (!blackOutLayer) { - // TODO: we could be more subtle with isFixedSize() - const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize(); - - // Query the texture matrix given our current filtering mode. - float textureMatrix[16]; - mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering); - mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix); - - if (getTransformToDisplayInverse()) { - - /* - * the code below applies the primary display's inverse transform to - * the texture transform - */ - uint32_t transform = - DisplayDevice::getPrimaryDisplayOrientationTransform(); - mat4 tr = inverseOrientation(transform); - - /** - * TODO(b/36727915): This is basically a hack. - * - * Ensure that regardless of the parent transformation, - * this buffer is always transformed from native display - * orientation to display orientation. For example, in the case - * of a camera where the buffer remains in native orientation, - * we want the pixels to always be upright. - */ - sp p = mDrawingParent.promote(); - if (p != nullptr) { - const auto parentTransform = p->getTransform(); - tr = tr * inverseOrientation(parentTransform.getOrientation()); - } - - // and finally apply it to the original texture matrix - const mat4 texTransform(mat4(static_cast(textureMatrix)) * tr); - memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix)); - } - - // Set things up for texturing. - mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight()); - mTexture.setFiltering(useFiltering); - mTexture.setMatrix(textureMatrix); - - engine.setupLayerTexturing(mTexture); - } else { - engine.setupLayerBlackedOut(); - } - drawWithOpenGL(renderArea, useIdentityTransform); - engine.disableTexturing(); -} - - void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue, float alpha) const @@ -1210,62 +942,6 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { clearWithOpenGL(renderArea, 0,0,0,0); } -void Layer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { - const State& s(getDrawingState()); - - computeGeometry(renderArea, mMesh, useIdentityTransform); - - /* - * NOTE: the way we compute the texture coordinates here produces - * different results than when we take the HWC path -- in the later case - * the "source crop" is rounded to texel boundaries. - * This can produce significantly different results when the texture - * is scaled by a large amount. - * - * The GL code below is more logical (imho), and the difference with - * HWC is due to a limitation of the HWC API to integers -- a question - * is suspend is whether we should ignore this problem or revert to - * GL composition when a buffer scaling is applied (maybe with some - * minimal value)? Or, we could make GL behave like HWC -- but this feel - * like more of a hack. - */ - Rect win(computeBounds()); - - Transform t = getTransform(); - if (!s.finalCrop.isEmpty()) { - win = t.transform(win); - if (!win.intersect(s.finalCrop, &win)) { - win.clear(); - } - win = t.inverse().transform(win); - if (!win.intersect(computeBounds(), &win)) { - win.clear(); - } - } - - float left = float(win.left) / float(s.active.w); - float top = float(win.top) / float(s.active.h); - float right = float(win.right) / float(s.active.w); - float bottom = float(win.bottom) / float(s.active.h); - - // TODO: we probably want to generate the texture coords with the mesh - // here we assume that we only have 4 vertices - Mesh::VertexArray texCoords(mMesh.getTexCoordArray()); - texCoords[0] = vec2(left, 1.0f - top); - texCoords[1] = vec2(left, 1.0f - bottom); - texCoords[2] = vec2(right, 1.0f - bottom); - texCoords[3] = vec2(right, 1.0f - top); - - RenderEngine& engine(mFlinger->getRenderEngine()); - engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), - false /* disableTexture */, getColor()); -#ifdef USE_HWC2 - engine.setSourceDataSpace(mCurrentState.dataSpace); -#endif - engine.drawMesh(mMesh); - engine.disableBlending(); -} - #ifdef USE_HWC2 void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) { @@ -1320,64 +996,6 @@ bool Layer::getClearClientTarget(int32_t hwcId) const { } #endif -uint32_t Layer::getProducerStickyTransform() const { - int producerStickyTransform = 0; - int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform); - if (ret != OK) { - ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__, - strerror(-ret), ret); - return 0; - } - return static_cast(producerStickyTransform); -} - -bool Layer::latchUnsignaledBuffers() { - static bool propertyLoaded = false; - static bool latch = false; - static std::mutex mutex; - std::lock_guard lock(mutex); - if (!propertyLoaded) { - char value[PROPERTY_VALUE_MAX] = {}; - property_get("debug.sf.latch_unsignaled", value, "0"); - latch = atoi(value); - propertyLoaded = true; - } - return latch; -} - -uint64_t Layer::getHeadFrameNumber() const { - Mutex::Autolock lock(mQueueItemLock); - if (!mQueueItems.empty()) { - return mQueueItems[0].mFrameNumber; - } else { - return mCurrentFrameNumber; - } -} - -bool Layer::headFenceHasSignaled() const { -#ifdef USE_HWC2 - if (latchUnsignaledBuffers()) { - return true; - } - - Mutex::Autolock lock(mQueueItemLock); - if (mQueueItems.empty()) { - return true; - } - if (mQueueItems[0].mIsDroppable) { - // Even though this buffer's fence may not have signaled yet, it could - // be replaced by another buffer before it has a chance to, which means - // that it's possible to get into a situation where a buffer is never - // able to be latched. To avoid this, grab this buffer anyway. - return true; - } - return mQueueItems[0].mFenceTime->getSignalTime() != - Fence::SIGNAL_TIME_PENDING; -#else - return true; -#endif -} - bool Layer::addSyncPoint(const std::shared_ptr& point) { if (point->getFrameNumber() <= mCurrentFrameNumber) { // Don't bother with a SyncPoint, since we've already latched the @@ -1398,28 +1016,6 @@ bool Layer::getFiltering() const { return mFiltering; } -// As documented in libhardware header, formats in the range -// 0x100 - 0x1FF are specific to the HAL implementation, and -// are known to have no alpha channel -// TODO: move definition for device-specific range into -// hardware.h, instead of using hard-coded values here. -#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF) - -bool Layer::getOpacityForFormat(uint32_t format) { - if (HARDWARE_IS_DEVICE_FORMAT(format)) { - return true; - } - switch (format) { - case HAL_PIXEL_FORMAT_RGBA_8888: - case HAL_PIXEL_FORMAT_BGRA_8888: - case HAL_PIXEL_FORMAT_RGBA_FP16: - case HAL_PIXEL_FORMAT_RGBA_1010102: - return false; - } - // in all other case, we have no blending (also for unknown formats) - return true; -} - // ---------------------------------------------------------------------------- // local state // ---------------------------------------------------------------------------- @@ -1476,44 +1072,12 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, } } -bool Layer::isOpaque(const Layer::State& s) const -{ - // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the - // layer's opaque flag. - if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) { - return false; - } - - // if the layer has the opaque flag, then we're always opaque, - // otherwise we use the current buffer's format. - return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity; -} - bool Layer::isSecure() const { const Layer::State& s(mDrawingState); return (s.flags & layer_state_t::eLayerSecure); } -bool Layer::isProtected() const -{ - const sp& activeBuffer(mActiveBuffer); - return (activeBuffer != 0) && - (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); -} - -bool Layer::isFixedSize() const { - return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE; -} - -bool Layer::isCropped() const { - return !mCurrentCrop.isEmpty(); -} - -bool Layer::needsFiltering(const RenderArea& renderArea) const { - return mNeedsFiltering || renderArea.needsFiltering(); -} - void Layer::setVisibleRegion(const Region& visibleRegion) { // always called from main thread this->visibleRegion = visibleRegion; @@ -1632,17 +1196,6 @@ bool Layer::applyPendingStates(State* stateToCommit) { return stateUpdateAvailable; } -void Layer::notifyAvailableFrames() { - auto headFrameNumber = getHeadFrameNumber(); - bool headFenceSignaled = headFenceHasSignaled(); - Mutex::Autolock lock(mLocalSyncPointMutex); - for (auto& point : mLocalSyncPoints) { - if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) { - point->setFrameAvailable(); - } - } -} - uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); @@ -1657,7 +1210,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h); - if (sizeChanged) { + if (mSurfaceFlingerConsumer && sizeChanged) { // the size changed, we need to ask our client to request a new buffer ALOGD_IF(DEBUG_RESIZE, "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n" @@ -1984,13 +1537,6 @@ void Layer::setInfo(uint32_t type, uint32_t appId) { setTransactionFlags(eTransactionNeeded); } -uint32_t Layer::getEffectiveScalingMode() const { - if (mOverrideScalingMode >= 0) { - return mOverrideScalingMode; - } - return mCurrentScalingMode; -} - bool Layer::setLayerStack(uint32_t layerStack) { if (mCurrentState.layerStack == layerStack) return false; @@ -2081,15 +1627,6 @@ bool Layer::shouldPresentNow(const DispSync& dispSync) const { return isDue || !isPlausible; } -bool Layer::onPreComposition(nsecs_t refreshStartTime) { - if (mBufferLatched) { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); - } - mRefreshPending = false; - return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; -} - bool Layer::onPostComposition(const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, const CompositorTiming& compositorTiming) { @@ -2135,25 +1672,6 @@ bool Layer::onPostComposition(const std::shared_ptr& glDoneFence, return true; } -#ifdef USE_HWC2 -void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { - if (!mSurfaceFlingerConsumer->releasePendingBuffer()) { - return; - } - - auto releaseFenceTime = std::make_shared( - mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); - mReleaseTimeline.updateSignalTimes(); - mReleaseTimeline.push(releaseFenceTime); - - Mutex::Autolock lock(mFrameEventHistoryMutex); - if (mPreviousFrameNumber != 0) { - mFrameEventHistory.addRelease(mPreviousFrameNumber, - dequeueReadyTime, std::move(releaseFenceTime)); - } -} -#endif - bool Layer::isHiddenByPolicy() const { const Layer::State& s(mDrawingState); const auto& parent = mDrawingParent.promote(); @@ -2163,249 +1681,6 @@ bool Layer::isHiddenByPolicy() const { return s.flags & layer_state_t::eLayerHidden; } -bool Layer::isVisible() const { - return !(isHiddenByPolicy()) && getAlpha() > 0.0f - && (mActiveBuffer != NULL || mSidebandStream != NULL); -} - -bool Layer::allTransactionsSignaled() { - auto headFrameNumber = getHeadFrameNumber(); - bool matchingFramesFound = false; - bool allTransactionsApplied = true; - Mutex::Autolock lock(mLocalSyncPointMutex); - - for (auto& point : mLocalSyncPoints) { - if (point->getFrameNumber() > headFrameNumber) { - break; - } - matchingFramesFound = true; - - if (!point->frameIsAvailable()) { - // We haven't notified the remote layer that the frame for - // this point is available yet. Notify it now, and then - // abort this attempt to latch. - point->setFrameAvailable(); - allTransactionsApplied = false; - break; - } - - allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied(); - } - return !matchingFramesFound || allTransactionsApplied; -} - -Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) -{ - ATRACE_CALL(); - - if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { - // mSidebandStreamChanged was true - mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream(); - if (mSidebandStream != NULL) { - setTransactionFlags(eTransactionNeeded); - mFlinger->setTransactionFlags(eTraversalNeeded); - } - recomputeVisibleRegions = true; - - const State& s(getDrawingState()); - return getTransform().transform(Region(Rect(s.active.w, s.active.h))); - } - - Region outDirtyRegion; - if (mQueuedFrames <= 0 && !mAutoRefresh) { - return outDirtyRegion; - } - - // if we've already called updateTexImage() without going through - // a composition step, we have to skip this layer at this point - // because we cannot call updateTeximage() without a corresponding - // compositionComplete() call. - // we'll trigger an update in onPreComposition(). - if (mRefreshPending) { - return outDirtyRegion; - } - - // If the head buffer's acquire fence hasn't signaled yet, return and - // try again later - if (!headFenceHasSignaled()) { - mFlinger->signalLayerUpdate(); - return outDirtyRegion; - } - - // Capture the old state of the layer for comparisons later - const State& s(getDrawingState()); - const bool oldOpacity = isOpaque(s); - sp oldActiveBuffer = mActiveBuffer; - - if (!allTransactionsSignaled()) { - mFlinger->signalLayerUpdate(); - return outDirtyRegion; - } - - // This boolean is used to make sure that SurfaceFlinger's shadow copy - // of the buffer queue isn't modified when the buffer queue is returning - // BufferItem's that weren't actually queued. This can happen in shared - // buffer mode. - bool queuedBuffer = false; - LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, - getProducerStickyTransform() != 0, mName.string(), - mOverrideScalingMode, mFreezeGeometryUpdates); - status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r, - mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer, - mLastFrameNumberReceived); - if (updateResult == BufferQueue::PRESENT_LATER) { - // Producer doesn't want buffer to be displayed yet. Signal a - // layer update so we check again at the next opportunity. - mFlinger->signalLayerUpdate(); - return outDirtyRegion; - } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) { - // If the buffer has been rejected, remove it from the shadow queue - // and return early - if (queuedBuffer) { - Mutex::Autolock lock(mQueueItemLock); - mQueueItems.removeAt(0); - android_atomic_dec(&mQueuedFrames); - } - return outDirtyRegion; - } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) { - // This can occur if something goes wrong when trying to create the - // EGLImage for this buffer. If this happens, the buffer has already - // been released, so we need to clean up the queue and bug out - // early. - if (queuedBuffer) { - Mutex::Autolock lock(mQueueItemLock); - mQueueItems.clear(); - android_atomic_and(0, &mQueuedFrames); - } - - // Once we have hit this state, the shadow queue may no longer - // correctly reflect the incoming BufferQueue's contents, so even if - // updateTexImage starts working, the only safe course of action is - // to continue to ignore updates. - mUpdateTexImageFailed = true; - - return outDirtyRegion; - } - - if (queuedBuffer) { - // Autolock scope - auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); - - Mutex::Autolock lock(mQueueItemLock); - - // Remove any stale buffers that have been dropped during - // updateTexImage - while (mQueueItems[0].mFrameNumber != currentFrameNumber) { - mQueueItems.removeAt(0); - android_atomic_dec(&mQueuedFrames); - } - - mQueueItems.removeAt(0); - } - - - // Decrement the queued-frames count. Signal another event if we - // have more frames pending. - if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) - || mAutoRefresh) { - mFlinger->signalLayerUpdate(); - } - - // update the active buffer - mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer( - &mActiveBufferSlot); - if (mActiveBuffer == NULL) { - // this can only happen if the very first buffer was rejected. - return outDirtyRegion; - } - - mBufferLatched = true; - mPreviousFrameNumber = mCurrentFrameNumber; - mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); - - { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); -#ifndef USE_HWC2 - auto releaseFenceTime = std::make_shared( - mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); - mReleaseTimeline.updateSignalTimes(); - mReleaseTimeline.push(releaseFenceTime); - if (mPreviousFrameNumber != 0) { - mFrameEventHistory.addRelease(mPreviousFrameNumber, - latchTime, std::move(releaseFenceTime)); - } -#endif - } - - mRefreshPending = true; - mFrameLatencyNeeded = true; - if (oldActiveBuffer == NULL) { - // the first time we receive a buffer, we need to trigger a - // geometry invalidation. - recomputeVisibleRegions = true; - } - - setDataSpace(mSurfaceFlingerConsumer->getCurrentDataSpace()); - - Rect crop(mSurfaceFlingerConsumer->getCurrentCrop()); - const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform()); - const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode()); - if ((crop != mCurrentCrop) || - (transform != mCurrentTransform) || - (scalingMode != mCurrentScalingMode)) - { - mCurrentCrop = crop; - mCurrentTransform = transform; - mCurrentScalingMode = scalingMode; - recomputeVisibleRegions = true; - } - - if (oldActiveBuffer != NULL) { - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); - if (bufWidth != uint32_t(oldActiveBuffer->width) || - bufHeight != uint32_t(oldActiveBuffer->height)) { - recomputeVisibleRegions = true; - } - } - - mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); - if (oldOpacity != isOpaque(s)) { - recomputeVisibleRegions = true; - } - - // Remove any sync points corresponding to the buffer which was just - // latched - { - Mutex::Autolock lock(mLocalSyncPointMutex); - auto point = mLocalSyncPoints.begin(); - while (point != mLocalSyncPoints.end()) { - if (!(*point)->frameIsAvailable() || - !(*point)->transactionIsApplied()) { - // This sync point must have been added since we started - // latching. Don't drop it yet. - ++point; - continue; - } - - if ((*point)->getFrameNumber() <= mCurrentFrameNumber) { - point = mLocalSyncPoints.erase(point); - } else { - ++point; - } - } - } - - // FIXME: postedRegion should be dirty & bounds - Region dirtyRegion(Rect(s.active.w, s.active.h)); - - // transform the dirty region to window-manager space - outDirtyRegion = (getTransform().transform(dirtyRegion)); - - return outDirtyRegion; -} - uint32_t Layer::getEffectiveUsage(uint32_t usage) const { // TODO: should we do something special if mSecure is set? @@ -2432,7 +1707,9 @@ void Layer::updateTransformHint(const sp& hw) const { orientation = 0; } } - mSurfaceFlingerConsumer->setTransformHint(orientation); + if (mSurfaceFlingerConsumer) { + mSurfaceFlingerConsumer->setTransformHint(orientation); + } } // ---------------------------------------------------------------------------- @@ -2584,6 +1861,10 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, std::vector Layer::getOccupancyHistory( bool forceFlush) { std::vector history; + + if (!mSurfaceFlingerConsumer) + return {}; + status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush, &history); if (result != NO_ERROR) { @@ -2595,7 +1876,10 @@ std::vector Layer::getOccupancyHistory( } bool Layer::getTransformToDisplayInverse() const { - return mSurfaceFlingerConsumer->getTransformToDisplayInverse(); + if (mSurfaceFlingerConsumer) { + return mSurfaceFlingerConsumer->getTransformToDisplayInverse(); + } + return false; } size_t Layer::getChildrenCount() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d75e175f5a..ee3bb7ef3f 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -69,14 +69,8 @@ class LayerDebugInfo; // --------------------------------------------------------------------------- -/* - * A new BufferQueue and a new SurfaceFlingerConsumer are created when the - * Layer is first referenced. - * - * This also implements onFrameAvailable(), which notifies SurfaceFlinger - * that new data has arrived. - */ -class Layer : public SurfaceFlingerConsumer::ContentsChangedListener { +class Layer : public virtual RefBase +{ static int32_t sSequence; public: @@ -162,18 +156,12 @@ public: half4 color; }; - // ----------------------------------------------------------------------- - Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags); - virtual ~Layer(); void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; } - // the this layer's size and format - status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); - // ------------------------------------------------------------------------ // Geometry setting functions. // @@ -264,8 +252,7 @@ public: // ----------------------------------------------------------------------- // Virtuals - - virtual const char* getTypeId() const { return "Layer"; } + virtual const char* getTypeId() const = 0; /* * isOpaque - true if this surface is opaque @@ -274,24 +261,18 @@ public: * pixel format includes an alpha channel) and the "opaque" flag set * on the layer. It does not examine the current plane alpha value. */ - virtual bool isOpaque(const Layer::State& s) const; + virtual bool isOpaque(const Layer::State& s) const = 0; /* * isSecure - true if this surface is secure, that is if it prevents * screenshots or VNC servers. */ - virtual bool isSecure() const; - - /* - * isProtected - true if the layer may contain protected content in the - * GRALLOC_USAGE_PROTECTED sense. - */ - virtual bool isProtected() const; + bool isSecure() const; /* * isVisible - true if this layer is visible, false otherwise */ - virtual bool isVisible() const; + virtual bool isVisible() const = 0; /* * isHiddenByPolicy - true if this layer has been forced invisible. @@ -299,12 +280,12 @@ public: * For example if this layer has no active buffer, it may not be hidden by * policy, but it still can not be visible. */ - virtual bool isHiddenByPolicy() const; + bool isHiddenByPolicy() const; /* * isFixedSize - true if content has a fixed size */ - virtual bool isFixedSize() const; + virtual bool isFixedSize() const = 0; void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); @@ -313,11 +294,9 @@ protected: * onDraw - draws the surface. */ virtual void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const; + bool useIdentityTransform) const = 0; public: - // ----------------------------------------------------------------------- - #ifdef USE_HWC2 void setGeometry(const sp& displayDevice, uint32_t z); void forceClientComposition(int32_t hwcId); @@ -325,22 +304,17 @@ public: // callIntoHwc exists so we can update our local state and call // acceptDisplayChanges without unnecessarily updating the device's state - void setCompositionType(int32_t hwcId, HWC2::Composition type, - bool callIntoHwc = true); + void setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc = true); HWC2::Composition getCompositionType(int32_t hwcId) const; - void setClearClientTarget(int32_t hwcId, bool clear); bool getClearClientTarget(int32_t hwcId) const; - void updateCursorPosition(const sp& hw); #else void setGeometry(const sp& hw, - HWComposer::HWCLayerInterface& layer); - void setPerFrameData(const sp& hw, - HWComposer::HWCLayerInterface& layer); + HWComposer::HWCLayerInterface& layer); + void setPerFrameData(const sp& hw, HWComposer::HWCLayerInterface& layer); void setAcquireFence(const sp& hw, - HWComposer::HWCLayerInterface& layer); - + HWComposer::HWCLayerInterface& layer); Rect getPosition(const sp& hw); #endif @@ -360,7 +334,7 @@ public: * called before composition. * returns true if the layer has pending updates. */ - bool onPreComposition(nsecs_t refreshStartTime); + virtual bool onPreComposition(nsecs_t refreshStartTime) = 0; /* * called after composition. @@ -372,7 +346,7 @@ public: #ifdef USE_HWC2 // If a buffer was replaced this frame, release the former buffer - void releasePendingBuffer(nsecs_t dequeueReadyTime); + virtual void releasePendingBuffer(nsecs_t dequeueReadyTime) = 0; #endif /* @@ -415,11 +389,10 @@ public: * operation, so this should be set only if needed). Typically this is used * to figure out if the content or size of a surface has changed. */ - Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime); - bool isBufferLatched() const { return mRefreshPending; } - - bool isPotentialCursor() const { return mPotentialCursor;} + virtual Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0; + virtual bool isBufferLatched() const = 0; + bool isPotentialCursor() const { return mPotentialCursor; } /* * called with the state lock from a binder thread when the layer is * removed from the current list to the pending removal list @@ -526,14 +499,12 @@ public: ssize_t removeChild(const sp& layer); sp getParent() const { return mCurrentParent.promote(); } bool hasParent() const { return getParent() != nullptr; } - Rect computeScreenBounds(bool reduceTransparentRegion = true) const; bool setChildLayer(const sp& childLayer, int32_t z); // Copy the current list of children to the drawing state. Called by // SurfaceFlinger to complete a transaction. void commitChildList(); - int32_t getZ() const; protected: // constant @@ -562,39 +533,21 @@ protected: -private: friend class SurfaceInterceptor; - // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener - virtual void onFrameAvailable(const BufferItem& item) override; - virtual void onFrameReplaced(const BufferItem& item) override; - virtual void onSidebandStreamChanged() override; - void commitTransaction(const State& stateToCommit); - // needsLinearFiltering - true if this surface's state requires filtering - bool needsFiltering(const RenderArea& renderArea) const; - uint32_t getEffectiveUsage(uint32_t usage) const; FloatRect computeCrop(const sp& hw) const; - // Compute the initial crop as specified by parent layers and the SurfaceControl - // for this layer. Does not include buffer crop from the IGraphicBufferProducer - // client, as that should not affect child clipping. Returns in screen space. + // Compute the initial crop as specified by parent layers and the + // SurfaceControl for this layer. Does not include buffer crop from the + // IGraphicBufferProducer client, as that should not affect child clipping. + // Returns in screen space. Rect computeInitialCrop(const sp& hw) const; - bool isCropped() const; - static bool getOpacityForFormat(uint32_t format); // drawing void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b, float alpha) const; - void drawWithOpenGL(const RenderArea& renderArea, - bool useIdentityTransform) const; - - // Temporary - Used only for LEGACY camera mode. - uint32_t getProducerStickyTransform() const; - - // Loads the corresponding system property once per process - static bool latchUnsignaledBuffers(); void setParent(const sp& layer); @@ -602,8 +555,7 @@ private: void addZOrderRelative(const wp& relative); void removeZOrderRelative(const wp& relative); - // ----------------------------------------------------------------------- - +protected: class SyncPoint { public: @@ -646,9 +598,6 @@ private: // is applied std::list> mRemoteSyncPoints; - uint64_t getHeadFrameNumber() const; - bool headFenceHasSignaled() const; - // Returns false if the relevant frame has already been latched bool addSyncPoint(const std::shared_ptr& point); @@ -661,7 +610,7 @@ private: // Returns mCurrentScaling mode (originating from the // Client) or mOverrideScalingMode mode (originating from // the Surface Controller) if set. - uint32_t getEffectiveScalingMode() const; + virtual uint32_t getEffectiveScalingMode() const = 0; public: /* * The layer handle is just a BBinder object passed to the client @@ -680,28 +629,19 @@ public: }; sp getHandle(); - sp getProducer() const; const String8& getName() const; - void notifyAvailableFrames(); - PixelFormat getPixelFormat() const { return mFormat; } + virtual void notifyAvailableFrames() = 0; + virtual PixelFormat getPixelFormat() const = 0; bool getPremultipledAlpha() const; -private: +protected: // ----------------------------------------------------------------------- - // Check all of the local sync points to ensure that all transactions - // which need to have been applied prior to the frame which is about to - // be latched have signaled - bool allTransactionsSignaled(); - // constants sp mSurfaceFlingerConsumer; - sp mProducer; - uint32_t mTextureName; // from GLES bool mPremultipliedAlpha; String8 mName; - String8 mTransactionName; // A cached version of "TX - " + mName for systraces - PixelFormat mFormat; + String8 mTransactionName; // A cached version of "TX - " + mName for systraces bool mPrimaryDisplayOnly = false; @@ -716,7 +656,7 @@ private: // thread-safe volatile int32_t mQueuedFrames; - volatile int32_t mSidebandStreamChanged; // used like an atomic boolean + volatile int32_t mSidebandStreamChanged; // used like an atomic boolean // Timestamp history for UIAutomation. Thread safe. FrameTracker mFrameTracker; @@ -734,14 +674,10 @@ private: sp mSidebandStream; Rect mCurrentCrop; uint32_t mCurrentTransform; - uint32_t mCurrentScalingMode; // We encode unset as -1. int32_t mOverrideScalingMode; bool mCurrentOpacity; - bool mBufferLatched = false; // TODO: Use mActiveBuffer? std::atomic mCurrentFrameNumber; - uint64_t mPreviousFrameNumber; // Only accessed on the main thread. - bool mRefreshPending; bool mFrameLatencyNeeded; // Whether filtering is forced on or not bool mFiltering; @@ -749,8 +685,7 @@ private: bool mNeedsFiltering; // The mesh used to draw the layer in GLES composition mode mutable Mesh mMesh; - // The texture used to draw the layer in GLES composition mode - mutable Texture mTexture; + #ifdef USE_HWC2 // HWC items, accessed from the main thread @@ -786,8 +721,7 @@ private: // protected by mLock mutable Mutex mLock; - // Set to true once we've returned this surface's handle - mutable bool mHasSurface; + const wp mClientRef; // This layer can be a cursor on some displays. @@ -798,8 +732,6 @@ private: Condition mQueueItemCondition; Vector mQueueItems; std::atomic mLastFrameNumberReceived; - bool mUpdateTexImageFailed; // This is only accessed on the main thread. - bool mAutoRefresh; bool mFreezeGeometryUpdates; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 77b9a296dc..e40bbd561e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -72,6 +72,7 @@ #include "EventControlThread.h" #include "EventThread.h" #include "Layer.h" +#include "BufferLayer.h" #include "LayerVector.h" #include "ColorLayer.h" #include "MonitoredProducer.h" @@ -3208,14 +3209,15 @@ status_t SurfaceFlinger::createLayer( switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: - result = createNormalLayer(client, + result = createBufferLayer(client, uniqueName, w, h, flags, format, handle, gbp, &layer); + break; case ISurfaceComposerClient::eFXSurfaceColor: result = createColorLayer(client, uniqueName, w, h, flags, - handle, gbp, &layer); + handle, &layer); break; default: result = BAD_VALUE; @@ -3269,7 +3271,7 @@ String8 SurfaceFlinger::getUniqueLayerName(const String8& name) return uniqueName; } -status_t SurfaceFlinger::createNormalLayer(const sp& client, +status_t SurfaceFlinger::createBufferLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, sp* handle, sp* gbp, sp* outLayer) { @@ -3284,24 +3286,24 @@ status_t SurfaceFlinger::createNormalLayer(const sp& client, break; } - *outLayer = new Layer(this, client, name, w, h, flags); - status_t err = (*outLayer)->setBuffers(w, h, format, flags); + sp layer = new BufferLayer(this, client, name, w, h, flags); + status_t err = layer->setBuffers(w, h, format, flags); if (err == NO_ERROR) { - *handle = (*outLayer)->getHandle(); - *gbp = (*outLayer)->getProducer(); + *handle = layer->getHandle(); + *gbp = layer->getProducer(); + *outLayer = layer; } - ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err)); + ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err)); return err; } status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, - sp* handle, sp* gbp, sp* outLayer) + sp* handle, sp* outLayer) { *outLayer = new ColorLayer(this, client, name, w, h, flags); *handle = (*outLayer)->getHandle(); - *gbp = (*outLayer)->getProducer(); return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d0f4699b82..d10b41bd34 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -244,6 +244,7 @@ private: friend class DisplayEventConnection; friend class EventThread; friend class Layer; + friend class BufferLayer; friend class MonitoredProducer; // This value is specified in number of frames. Log frame stats at most @@ -419,14 +420,14 @@ private: uint32_t windowType, uint32_t ownerUid, sp* handle, sp* gbp, sp* parent); - status_t createNormalLayer(const sp& client, const String8& name, + status_t createBufferLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, sp* outHandle, sp* outGbp, sp* outLayer); status_t createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp* outHandle, - sp* outGbp, sp* outLayer); + sp* outLayer); String8 getUniqueLayerName(const String8& name); diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 952023ea19..714c23d9a9 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -70,6 +70,7 @@ #include "EventControlThread.h" #include "EventThread.h" #include "Layer.h" +#include "BufferLayer.h" #include "LayerVector.h" #include "ColorLayer.h" #include "MonitoredProducer.h" @@ -2733,14 +2734,14 @@ status_t SurfaceFlinger::createLayer( switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: - result = createNormalLayer(client, + result = createBufferLayer(client, uniqueName, w, h, flags, format, handle, gbp, &layer); break; case ISurfaceComposerClient::eFXSurfaceColor: result = createColorLayer(client, uniqueName, w, h, flags, - handle, gbp, &layer); + handle, &layer); break; default: result = BAD_VALUE; @@ -2787,7 +2788,7 @@ String8 SurfaceFlinger::getUniqueLayerName(const String8& name) return uniqueName; } -status_t SurfaceFlinger::createNormalLayer(const sp& client, +status_t SurfaceFlinger::createBufferLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, sp* handle, sp* gbp, sp* outLayer) { @@ -2802,24 +2803,24 @@ status_t SurfaceFlinger::createNormalLayer(const sp& client, break; } - *outLayer = new Layer(this, client, name, w, h, flags); - status_t err = (*outLayer)->setBuffers(w, h, format, flags); + sp layer = new BufferLayer(this, client, name, w, h, flags); + status_t err = layer->setBuffers(w, h, format, flags); if (err == NO_ERROR) { - *handle = (*outLayer)->getHandle(); - *gbp = (*outLayer)->getProducer(); + *handle = layer->getHandle(); + *gbp = layer->getProducer(); + *outLayer = layer; } - ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err)); + ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err)); return err; } status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, - sp* handle, sp* gbp, sp* outLayer) + sp* handle, sp* outLayer) { *outLayer = new ColorLayer(this, client, name, w, h, flags); *handle = (*outLayer)->getHandle(); - *gbp = (*outLayer)->getProducer(); return NO_ERROR; } -- cgit v1.2.3-59-g8ed1b From 8b3871addb9bbd5776f4ed59e67af2baa9c583fd Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 1 Nov 2017 17:41:01 -0700 Subject: Don't invoke transactions on layers that will be removed. A layer can be marked as removed, but still be present in memory. This check ensures that transactions aren't invoked on layers that will be removed on the next commitTransaction. Normally, this would be harmless since the layer will get removed as soon as a commitTransaction is called. However, for cases like re-parenting, a removed child layer can be re-parented to a non-removed layer, which prevents the child from getting removed. Test: Added code that would destroy a layer before the re-parent was called. Ensure that the re-parent was ignored. There doesn't seem to be an easy way to write a test case right now. Change-Id: I17614447fc4253bdbbb0c06469bb09117b55c1ab --- services/surfaceflinger/Layer.cpp | 2 + services/surfaceflinger/Layer.h | 4 + services/surfaceflinger/SurfaceFlinger.cpp | 228 +++++++++++++++-------------- 3 files changed, 126 insertions(+), 108 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a318a8f46a..136fbc1b21 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -175,6 +175,8 @@ void Layer::onLayerDisplayed(const sp& /* hw */, void Layer::onRemovedFromCurrentState() { // the layer is removed from SF mCurrentState to mLayersPendingRemoval + mPendingRemoval = true; + if (mCurrentState.zOrderRelativeOf != nullptr) { sp strongRelative = mCurrentState.zOrderRelativeOf.promote(); if (strongRelative != nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index db94a31c5e..3099382f38 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -283,6 +283,8 @@ public: */ virtual bool isFixedSize() const = 0; + bool isPendingRemoval() const { return mPendingRemoval; } + void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); @@ -666,6 +668,8 @@ protected: // The mesh used to draw the layer in GLES composition mode mutable Mesh mMesh; + bool mPendingRemoval = false; + #ifdef USE_HWC2 // HWC items, accessed from the main thread struct HWCInfo { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e40bbd561e..4ca9acbcf2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2857,6 +2857,10 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, status_t SurfaceFlinger::removeLayer(const sp& layer, bool topLevelOnly) { Mutex::Autolock _l(mStateLock); + if (layer->isPendingRemoval()) { + return NO_ERROR; + } + const auto& p = layer->getParent(); ssize_t index; if (p != nullptr) { @@ -3060,131 +3064,139 @@ uint32_t SurfaceFlinger::setClientStateLocked( const sp& client, const layer_state_t& s) { - uint32_t flags = 0; sp layer(client->getLayerUser(s.surface)); - if (layer != 0) { - const uint32_t what = s.what; - bool geometryAppliesWithResize = - what & layer_state_t::eGeometryAppliesWithResize; - if (what & layer_state_t::ePositionChanged) { - if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) { - flags |= eTraversalNeeded; - } - } - if (what & layer_state_t::eLayerChanged) { - // NOTE: index needs to be calculated before we update the state - const auto& p = layer->getParent(); - if (p == nullptr) { - ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setLayer(s.z) && idx >= 0) { - mCurrentState.layersSortedByZ.removeAt(idx); - mCurrentState.layersSortedByZ.add(layer); - // we need traversal (state changed) - // AND transaction (list changed) - flags |= eTransactionNeeded|eTraversalNeeded; - } - } else { - if (p->setChildLayer(layer, s.z)) { - flags |= eTransactionNeeded|eTraversalNeeded; - } - } - } - if (what & layer_state_t::eRelativeLayerChanged) { - ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) { - mCurrentState.layersSortedByZ.removeAt(idx); - mCurrentState.layersSortedByZ.add(layer); - flags |= eTransactionNeeded|eTraversalNeeded; - } - } - if (what & layer_state_t::eSizeChanged) { - if (layer->setSize(s.w, s.h)) { - flags |= eTraversalNeeded; - } - } - if (what & layer_state_t::eAlphaChanged) { - if (layer->setAlpha(s.alpha)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eColorChanged) { - if (layer->setColor(s.color)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eMatrixChanged) { - if (layer->setMatrix(s.matrix)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eTransparentRegionChanged) { - if (layer->setTransparentRegionHint(s.transparentRegion)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eFlagsChanged) { - if (layer->setFlags(s.flags, s.mask)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eCropChanged) { - if (layer->setCrop(s.crop, !geometryAppliesWithResize)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eFinalCropChanged) { - if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize)) - flags |= eTraversalNeeded; + if (layer == nullptr) { + return 0; + } + + if (layer->isPendingRemoval()) { + ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string()); + return 0; + } + + uint32_t flags = 0; + + const uint32_t what = s.what; + bool geometryAppliesWithResize = + what & layer_state_t::eGeometryAppliesWithResize; + if (what & layer_state_t::ePositionChanged) { + if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) { + flags |= eTraversalNeeded; } - if (what & layer_state_t::eLayerStackChanged) { + } + if (what & layer_state_t::eLayerChanged) { + // NOTE: index needs to be calculated before we update the state + const auto& p = layer->getParent(); + if (p == nullptr) { ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - // We only allow setting layer stacks for top level layers, - // everything else inherits layer stack from its parent. - if (layer->hasParent()) { - ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid", - layer->getName().string()); - } else if (idx < 0) { - ALOGE("Attempt to set layer stack on layer without parent (%s) that " - "that also does not appear in the top level layer list. Something" - " has gone wrong.", layer->getName().string()); - } else if (layer->setLayerStack(s.layerStack)) { + if (layer->setLayer(s.z) && idx >= 0) { mCurrentState.layersSortedByZ.removeAt(idx); mCurrentState.layersSortedByZ.add(layer); // we need traversal (state changed) // AND transaction (list changed) flags |= eTransactionNeeded|eTraversalNeeded; } - } - if (what & layer_state_t::eDeferTransaction) { - if (s.barrierHandle != nullptr) { - layer->deferTransactionUntil(s.barrierHandle, s.frameNumber); - } else if (s.barrierGbp != nullptr) { - const sp& gbp = s.barrierGbp; - if (authenticateSurfaceTextureLocked(gbp)) { - const auto& otherLayer = - (static_cast(gbp.get()))->getLayer(); - layer->deferTransactionUntil(otherLayer, s.frameNumber); - } else { - ALOGE("Attempt to defer transaction to to an" - " unrecognized GraphicBufferProducer"); - } - } - // We don't trigger a traversal here because if no other state is - // changed, we don't want this to cause any more work - } - if (what & layer_state_t::eReparent) { - if (layer->reparent(s.parentHandleForChild)) { + } else { + if (p->setChildLayer(layer, s.z)) { flags |= eTransactionNeeded|eTraversalNeeded; } } - if (what & layer_state_t::eReparentChildren) { - if (layer->reparentChildren(s.reparentHandle)) { - flags |= eTransactionNeeded|eTraversalNeeded; + } + if (what & layer_state_t::eRelativeLayerChanged) { + ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); + if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) { + mCurrentState.layersSortedByZ.removeAt(idx); + mCurrentState.layersSortedByZ.add(layer); + flags |= eTransactionNeeded|eTraversalNeeded; + } + } + if (what & layer_state_t::eSizeChanged) { + if (layer->setSize(s.w, s.h)) { + flags |= eTraversalNeeded; + } + } + if (what & layer_state_t::eAlphaChanged) { + if (layer->setAlpha(s.alpha)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eColorChanged) { + if (layer->setColor(s.color)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eMatrixChanged) { + if (layer->setMatrix(s.matrix)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eTransparentRegionChanged) { + if (layer->setTransparentRegionHint(s.transparentRegion)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eFlagsChanged) { + if (layer->setFlags(s.flags, s.mask)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eCropChanged) { + if (layer->setCrop(s.crop, !geometryAppliesWithResize)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eFinalCropChanged) { + if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eLayerStackChanged) { + ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); + // We only allow setting layer stacks for top level layers, + // everything else inherits layer stack from its parent. + if (layer->hasParent()) { + ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid", + layer->getName().string()); + } else if (idx < 0) { + ALOGE("Attempt to set layer stack on layer without parent (%s) that " + "that also does not appear in the top level layer list. Something" + " has gone wrong.", layer->getName().string()); + } else if (layer->setLayerStack(s.layerStack)) { + mCurrentState.layersSortedByZ.removeAt(idx); + mCurrentState.layersSortedByZ.add(layer); + // we need traversal (state changed) + // AND transaction (list changed) + flags |= eTransactionNeeded|eTraversalNeeded; + } + } + if (what & layer_state_t::eDeferTransaction) { + if (s.barrierHandle != nullptr) { + layer->deferTransactionUntil(s.barrierHandle, s.frameNumber); + } else if (s.barrierGbp != nullptr) { + const sp& gbp = s.barrierGbp; + if (authenticateSurfaceTextureLocked(gbp)) { + const auto& otherLayer = + (static_cast(gbp.get()))->getLayer(); + layer->deferTransactionUntil(otherLayer, s.frameNumber); + } else { + ALOGE("Attempt to defer transaction to to an" + " unrecognized GraphicBufferProducer"); } } - if (what & layer_state_t::eDetachChildren) { - layer->detachChildren(); + // We don't trigger a traversal here because if no other state is + // changed, we don't want this to cause any more work + } + if (what & layer_state_t::eReparent) { + if (layer->reparent(s.parentHandleForChild)) { + flags |= eTransactionNeeded|eTraversalNeeded; } - if (what & layer_state_t::eOverrideScalingModeChanged) { - layer->setOverrideScalingMode(s.overrideScalingMode); - // We don't trigger a traversal here because if no other state is - // changed, we don't want this to cause any more work + } + if (what & layer_state_t::eReparentChildren) { + if (layer->reparentChildren(s.reparentHandle)) { + flags |= eTransactionNeeded|eTraversalNeeded; } } + if (what & layer_state_t::eDetachChildren) { + layer->detachChildren(); + } + if (what & layer_state_t::eOverrideScalingModeChanged) { + layer->setOverrideScalingMode(s.overrideScalingMode); + // We don't trigger a traversal here because if no other state is + // changed, we don't want this to cause any more work + } return flags; } -- cgit v1.2.3-59-g8ed1b From 83ce7c162855742a2d9eeebc0cd70fe48d2cd125 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 19 Oct 2017 15:18:55 -0700 Subject: surfaceflinger: remove USE_HWC2 Remove USE_HWC2 and assume it to be true. Remove all !USE_HWC2 code. This also fixes a compile error in tests/fakehwc, which never defines USE_HWC2. Test: boots taimen and hikey960 Change-Id: Ie6d2fcf884aa6fc715ab0ce19a1e0f7c8acf734c --- services/surfaceflinger/Android.mk | 3 - services/surfaceflinger/BufferLayer.cpp | 55 ---------- services/surfaceflinger/BufferLayer.h | 12 --- services/surfaceflinger/ColorLayer.cpp | 2 - services/surfaceflinger/ColorLayer.h | 7 -- services/surfaceflinger/DisplayDevice.cpp | 79 -------------- services/surfaceflinger/DisplayDevice.h | 33 ------ .../DisplayHardware/DisplaySurface.h | 8 -- .../DisplayHardware/FramebufferSurface.cpp | 79 -------------- .../DisplayHardware/FramebufferSurface.h | 12 --- .../surfaceflinger/DisplayHardware/HWComposer.h | 6 -- .../DisplayHardware/VirtualDisplaySurface.cpp | 29 ------ .../DisplayHardware/VirtualDisplaySurface.h | 6 -- services/surfaceflinger/EventControlThread.cpp | 5 - services/surfaceflinger/Layer.cpp | 114 +-------------------- services/surfaceflinger/Layer.h | 23 ----- services/surfaceflinger/RenderArea.h | 4 +- .../RenderEngine/GLES20RenderEngine.cpp | 14 --- .../RenderEngine/GLES20RenderEngine.h | 2 - .../surfaceflinger/RenderEngine/RenderEngine.h | 2 - services/surfaceflinger/SurfaceFlinger.cpp | 2 - services/surfaceflinger/SurfaceFlinger.h | 50 --------- services/surfaceflinger/SurfaceFlingerConsumer.cpp | 6 -- services/surfaceflinger/SurfaceFlingerConsumer.h | 4 - .../tests/fakehwc/FakeComposerClient.h | 4 + 25 files changed, 6 insertions(+), 555 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 469e5989ba..2a78aa597f 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -54,7 +54,6 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -LOCAL_CFLAGS += -DUSE_HWC2 LOCAL_CFLAGS += -fvisibility=hidden -Werror=format @@ -120,8 +119,6 @@ LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_INIT_RC := surfaceflinger.rc -LOCAL_CFLAGS += -DUSE_HWC2 - LOCAL_SRC_FILES := \ main_surfaceflinger.cpp diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index fc0949dd90..0c1693b53b 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -61,9 +61,7 @@ BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp& client, cons mPreviousFrameNumber(0), mUpdateTexImageFailed(false), mRefreshPending(false) { -#ifdef USE_HWC2 ALOGV("Creating Layer %s", name.string()); -#endif mFlinger->getRenderEngine().genTextures(1, &mTextureName); mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); @@ -90,14 +88,12 @@ BufferLayer::~BufferLayer() { } mFlinger->deleteTextureAsync(mTextureName); -#ifdef USE_HWC2 if (!mHwcLayers.empty()) { ALOGE("Found stale hardware composer layers when destroying " "surface flinger layer %s", mName.string()); destroyAllHwcLayers(); } -#endif } void BufferLayer::useSurfaceDamage() { @@ -265,22 +261,12 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, engine.disableTexturing(); } -#ifdef USE_HWC2 void BufferLayer::onLayerDisplayed(const sp& releaseFence) { if (mHwcLayers.empty()) { return; } mSurfaceFlingerConsumer->setReleaseFence(releaseFence); } -#else -void BufferLayer::onLayerDisplayed(const sp& /*hw*/, - HWComposer::HWCLayerInterface* layer) { - if (layer) { - layer->onDisplayed(); - mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence()); - } -} -#endif void BufferLayer::abandon() { mSurfaceFlingerConsumer->abandon(); @@ -376,7 +362,6 @@ bool BufferLayer::getTransformToDisplayInverse() const { return mSurfaceFlingerConsumer->getTransformToDisplayInverse(); } -#ifdef USE_HWC2 void BufferLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { if (!mSurfaceFlingerConsumer->releasePendingBuffer()) { return; @@ -393,7 +378,6 @@ void BufferLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { std::move(releaseFenceTime)); } } -#endif Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) { ATRACE_CALL(); @@ -523,16 +507,6 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); -#ifndef USE_HWC2 - auto releaseFenceTime = - std::make_shared(mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); - mReleaseTimeline.updateSignalTimes(); - mReleaseTimeline.push(releaseFenceTime); - if (mPreviousFrameNumber != 0) { - mFrameEventHistory.addRelease(mPreviousFrameNumber, latchTime, - std::move(releaseFenceTime)); - } -#endif } mRefreshPending = true; @@ -604,7 +578,6 @@ void BufferLayer::setDefaultBufferSize(uint32_t w, uint32_t h) { mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); } -#ifdef USE_HWC2 void BufferLayer::setPerFrameData(const sp& displayDevice) { // Apply this display's projection's viewport to the visible region // before giving it to the HWC HAL. @@ -676,28 +649,6 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) } } -#else -void BufferLayer::setAcquireFence(const sp& /* hw */, - HWComposer::HWCLayerInterface& layer) { - int fenceFd = -1; - - // TODO: there is a possible optimization here: we only need to set the - // acquire fence the first time a new buffer is acquired on EACH display. - - if (layer.getCompositionType() == HWC_OVERLAY || - layer.getCompositionType() == HWC_CURSOR_OVERLAY) { - sp fence = mSurfaceFlingerConsumer->getCurrentFence(); - if (fence->isValid()) { - fenceFd = fence->dup(); - if (fenceFd == -1) { - ALOGW("failed to dup layer fence, skipping sync: %d", errno); - } - } - } - layer.setAcquireFenceFd(fenceFd); -} -#endif - bool BufferLayer::isOpaque(const Layer::State& s) const { // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the // layer's opaque flag. @@ -871,9 +822,7 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT RenderEngine& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */, getColor()); -#ifdef USE_HWC2 engine.setSourceDataSpace(mCurrentState.dataSpace); -#endif engine.drawMesh(mMesh); engine.disableBlending(); } @@ -913,7 +862,6 @@ uint64_t BufferLayer::getHeadFrameNumber() const { } bool BufferLayer::headFenceHasSignaled() const { -#ifdef USE_HWC2 if (latchUnsignaledBuffers()) { return true; } @@ -930,9 +878,6 @@ bool BufferLayer::headFenceHasSignaled() const { return true; } return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; -#else - return true; -#endif } uint32_t BufferLayer::getEffectiveScalingMode() const { diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 418f032198..078302bc75 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -105,12 +105,7 @@ public: void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const override; -#ifdef USE_HWC2 void onLayerDisplayed(const sp& releaseFence) override; -#else - void onLayerDisplayed(const sp& hw, - HWComposer::HWCLayerInterface* layer) override; -#endif void abandon() override; bool shouldPresentNow(const DispSync& dispSync) const override; @@ -124,10 +119,8 @@ public: public: bool onPreComposition(nsecs_t refreshStartTime) override; -#ifdef USE_HWC2 // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime); -#endif /* * latchBuffer - called each time the screen is redrawn and returns whether @@ -139,12 +132,7 @@ public: bool isBufferLatched() const override { return mRefreshPending; } void setDefaultBufferSize(uint32_t w, uint32_t h) override; -#ifdef USE_HWC2 void setPerFrameData(const sp& displayDevice) override; -#else - void setAcquireFence(const sp& hw, - HWComposer::HWCLayerInterface& layer) override; -#endif bool isOpaque(const Layer::State& s) const override; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 8a17f882d0..292e1a7350 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -61,7 +61,6 @@ bool ColorLayer::isVisible() const { return !isHiddenByPolicy() && s.color.a; } -#ifdef USE_HWC2 void ColorLayer::setPerFrameData(const sp& displayDevice) { const Transform& tr = displayDevice->getTransform(); const auto& viewport = displayDevice->getViewport(); @@ -89,7 +88,6 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { static_cast(error)); } } -#endif // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index debd3c3869..4022b319fa 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -42,21 +42,14 @@ public: void notifyAvailableFrames() override {} PixelFormat getPixelFormat() const override { return PIXEL_FORMAT_NONE; } uint32_t getEffectiveScalingMode() const override { return 0; } -#ifdef USE_HWC2 void releasePendingBuffer(nsecs_t) override {} -#endif Region latchBuffer(bool&, nsecs_t) override { return Region(); } void useSurfaceDamage() override {} void useEmptyDamage() override {} bool isBufferLatched() const override { return false; } bool onPreComposition(nsecs_t) override { return true; } void abandon() override {} -#ifdef USE_HWC2 void setPerFrameData(const sp& displayDevice) override; -#else - void setAcquireFence(const sp& /*hw*/, - HWComposer::HWCLayerInterface& /*layer*/) override {} -#endif void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) override {} bool shouldPresentNow(const DispSync& /*dispSync*/) const override { return false; } bool onPostComposition(const std::shared_ptr& /*glDoneFence*/, diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 0244c1b862..ef7d482f28 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -38,9 +38,7 @@ #include "DisplayHardware/DisplaySurface.h" #include "DisplayHardware/HWComposer.h" -#ifdef USE_HWC2 #include "DisplayHardware/HWC2.h" -#endif #include "RenderEngine/RenderEngine.h" #include "clz.h" @@ -86,9 +84,6 @@ DisplayDevice::DisplayDevice( const sp& flinger, DisplayType type, int32_t hwcId, -#ifndef USE_HWC2 - int format, -#endif bool isSecure, const wp& displayToken, const sp& displaySurface, @@ -105,9 +100,6 @@ DisplayDevice::DisplayDevice( mSurface(EGL_NO_SURFACE), mDisplayWidth(), mDisplayHeight(), -#ifndef USE_HWC2 - mFormat(), -#endif mFlags(), mPageFlipCount(), mIsSecure(isSecure), @@ -121,12 +113,8 @@ DisplayDevice::DisplayDevice( mNativeWindow = surface = new Surface(producer, false); ANativeWindow* const window = mNativeWindow.get(); -#ifdef USE_HWC2 mActiveColorMode = HAL_COLOR_MODE_NATIVE; mDisplayHasWideColor = supportWideColor; -#else - (void) supportWideColor; -#endif /* * Create our display's surface */ @@ -134,13 +122,8 @@ DisplayDevice::DisplayDevice( EGLSurface eglSurface; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (config == EGL_NO_CONFIG) { -#ifdef USE_HWC2 config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888, /*logConfig*/ false); -#else - config = RenderEngine::chooseEglConfig(display, format, - /*logConfig*/ false); -#endif } eglSurface = eglCreateWindowSurface(display, config, window, NULL); eglQuerySurface(display, eglSurface, EGL_WIDTH, &mDisplayWidth); @@ -159,9 +142,6 @@ DisplayDevice::DisplayDevice( mConfig = config; mDisplay = display; mSurface = eglSurface; -#ifndef USE_HWC2 - mFormat = format; -#endif mPageFlipCount = 0; mViewport.makeInvalid(); mFrame.makeInvalid(); @@ -202,10 +182,6 @@ DisplayDevice::~DisplayDevice() { void DisplayDevice::disconnect(HWComposer& hwc) { if (mHwcDisplayId >= 0) { hwc.disconnectDisplay(mHwcDisplayId); -#ifndef USE_HWC2 - if (mHwcDisplayId >= DISPLAY_VIRTUAL) - hwc.freeDisplayId(mHwcDisplayId); -#endif mHwcDisplayId = -1; } } @@ -222,12 +198,6 @@ int DisplayDevice::getHeight() const { return mDisplayHeight; } -#ifndef USE_HWC2 -PixelFormat DisplayDevice::getFormat() const { - return mFormat; -} -#endif - EGLSurface DisplayDevice::getEGLSurface() const { return mSurface; } @@ -243,12 +213,6 @@ uint32_t DisplayDevice::getPageFlipCount() const { return mPageFlipCount; } -#ifndef USE_HWC2 -status_t DisplayDevice::compositionComplete() const { - return mDisplaySurface->compositionComplete(); -} -#endif - void DisplayDevice::flip(const Region& dirty) const { mFlinger->getRenderEngine().checkErrors(); @@ -269,7 +233,6 @@ status_t DisplayDevice::beginFrame(bool mustRecompose) const { return mDisplaySurface->beginFrame(mustRecompose); } -#ifdef USE_HWC2 status_t DisplayDevice::prepareFrame(HWComposer& hwc) { status_t error = hwc.prepare(*this); if (error != NO_ERROR) { @@ -293,41 +256,9 @@ status_t DisplayDevice::prepareFrame(HWComposer& hwc) { } return mDisplaySurface->prepareFrame(compositionType); } -#else -status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const { - DisplaySurface::CompositionType compositionType; - bool haveGles = hwc.hasGlesComposition(mHwcDisplayId); - bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId); - if (haveGles && haveHwc) { - compositionType = DisplaySurface::COMPOSITION_MIXED; - } else if (haveGles) { - compositionType = DisplaySurface::COMPOSITION_GLES; - } else if (haveHwc) { - compositionType = DisplaySurface::COMPOSITION_HWC; - } else { - // Nothing to do -- when turning the screen off we get a frame like - // this. Call it a HWC frame since we won't be doing any GLES work but - // will do a prepare/set cycle. - compositionType = DisplaySurface::COMPOSITION_HWC; - } - return mDisplaySurface->prepareFrame(compositionType); -} -#endif void DisplayDevice::swapBuffers(HWComposer& hwc) const { -#ifdef USE_HWC2 if (hwc.hasClientComposition(mHwcDisplayId)) { -#else - // We need to call eglSwapBuffers() if: - // (1) we don't have a hardware composer, or - // (2) we did GLES composition this frame, and either - // (a) we have framebuffer target support (not present on legacy - // devices, where HWComposer::commit() handles things); or - // (b) this is a virtual display - if (hwc.initCheck() != NO_ERROR || - (hwc.hasGlesComposition(mHwcDisplayId) && - (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) { -#endif EGLBoolean success = eglSwapBuffers(mDisplay, mSurface); if (!success) { EGLint error = eglGetError(); @@ -349,17 +280,9 @@ void DisplayDevice::swapBuffers(HWComposer& hwc) const { } } -#ifdef USE_HWC2 void DisplayDevice::onSwapBuffersCompleted() const { mDisplaySurface->onFrameCommitted(); } -#else -void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const { - if (hwc.initCheck() == NO_ERROR) { - mDisplaySurface->onFrameCommitted(); - } -} -#endif uint32_t DisplayDevice::getFlags() const { @@ -437,7 +360,6 @@ int DisplayDevice::getActiveConfig() const { } // ---------------------------------------------------------------------------- -#ifdef USE_HWC2 void DisplayDevice::setActiveColorMode(android_color_mode_t mode) { mActiveColorMode = mode; } @@ -450,7 +372,6 @@ void DisplayDevice::setCompositionDataSpace(android_dataspace dataspace) { ANativeWindow* const window = mNativeWindow.get(); native_window_set_buffers_data_space(window, dataspace); } -#endif // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 49fef5805f..50e30b2571 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -21,18 +21,13 @@ #include -#ifndef USE_HWC2 -#include -#endif #include #include #include -#ifdef USE_HWC2 #include #include -#endif #include #include #include @@ -41,9 +36,7 @@ #include #include "RenderArea.h" -#ifdef USE_HWC2 #include -#endif struct ANativeWindow; @@ -90,9 +83,6 @@ public: const sp& flinger, DisplayType type, int32_t hwcId, -#ifndef USE_HWC2 - int format, -#endif bool isSecure, const wp& displayToken, const sp& displaySurface, @@ -117,9 +107,6 @@ public: int getWidth() const; int getHeight() const; -#ifndef USE_HWC2 - PixelFormat getFormat() const; -#endif uint32_t getFlags() const; EGLSurface getEGLSurface() const; @@ -150,24 +137,13 @@ public: // We pass in mustRecompose so we can keep VirtualDisplaySurface's state // machine happy without actually queueing a buffer if nothing has changed status_t beginFrame(bool mustRecompose) const; -#ifdef USE_HWC2 status_t prepareFrame(HWComposer& hwc); bool getWideColorSupport() const { return mDisplayHasWideColor; } -#else - status_t prepareFrame(const HWComposer& hwc) const; -#endif void swapBuffers(HWComposer& hwc) const; -#ifndef USE_HWC2 - status_t compositionComplete() const; -#endif // called after h/w composer has completed its set() call -#ifdef USE_HWC2 void onSwapBuffersCompleted() const; -#else - void onSwapBuffersCompleted(HWComposer& hwc) const; -#endif Rect getBounds() const { return Rect(mDisplayWidth, mDisplayHeight); @@ -189,11 +165,9 @@ public: void setPowerMode(int mode); bool isDisplayOn() const; -#ifdef USE_HWC2 android_color_mode_t getActiveColorMode() const; void setActiveColorMode(android_color_mode_t mode); void setCompositionDataSpace(android_dataspace dataspace); -#endif /* ------------------------------------------------------------------------ * Display active config management. @@ -228,9 +202,6 @@ private: EGLSurface mSurface; int mDisplayWidth; int mDisplayHeight; -#ifndef USE_HWC2 - PixelFormat mFormat; -#endif uint32_t mFlags; mutable uint32_t mPageFlipCount; String8 mDisplayName; @@ -269,7 +240,6 @@ private: int mPowerMode; // Current active config int mActiveConfig; -#ifdef USE_HWC2 // current active color mode android_color_mode_t mActiveColorMode; @@ -277,7 +247,6 @@ private: // Initialized by SurfaceFlinger when the DisplayDevice is created. // Fed to RenderEngine during composition. bool mDisplayHasWideColor; -#endif }; struct DisplayDeviceState { @@ -319,12 +288,10 @@ public: bool isSecure() const override { return mDevice->isSecure(); } bool needsFiltering() const override { return mDevice->needsFiltering(); } Rect getSourceCrop() const override { return mSourceCrop; } -#ifdef USE_HWC2 bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); } android_color_mode_t getActiveColorMode() const override { return mDevice->getActiveColorMode(); } -#endif private: const sp mDevice; diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h index cb08f084fe..f744f5cf21 100644 --- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h @@ -50,14 +50,6 @@ public: }; virtual status_t prepareFrame(CompositionType compositionType) = 0; -#ifndef USE_HWC2 - // Should be called when composition rendering is complete for a frame (but - // eglSwapBuffers hasn't necessarily been called). Required by certain - // older drivers for synchronization. - // TODO: Remove this when we drop support for HWC 1.0. - virtual status_t compositionComplete() = 0; -#endif - // Inform the surface that GLES composition is complete for this frame, and // the surface should make sure that HWComposer has the correct buffer for // this frame. Some implementations may only push a new buffer to diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 93c6d5486f..182629c97e 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -59,32 +59,21 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp, mCurrentBufferSlot(-1), mCurrentBuffer(), mCurrentFence(Fence::NO_FENCE), -#ifdef USE_HWC2 mHwc(hwc), mHasPendingRelease(false), mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), mPreviousBuffer() -#else - mHwc(hwc) -#endif { -#ifdef USE_HWC2 ALOGV("Creating for display %d", disp); -#endif mName = "FramebufferSurface"; mConsumer->setConsumerName(mName); mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER); -#ifdef USE_HWC2 const auto& activeConfig = mHwc.getActiveConfig(disp); mConsumer->setDefaultBufferSize(activeConfig->getWidth(), activeConfig->getHeight()); -#else - mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp)); - mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp)); -#endif mConsumer->setMaxAcquiredBufferCount( SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1); } @@ -98,7 +87,6 @@ status_t FramebufferSurface::prepareFrame(CompositionType /*compositionType*/) { } status_t FramebufferSurface::advanceFrame() { -#ifdef USE_HWC2 uint32_t slot = 0; sp buf; sp acquireFence(Fence::NO_FENCE); @@ -110,32 +98,18 @@ status_t FramebufferSurface::advanceFrame() { strerror(-result), result); } return result; -#else - // Once we remove FB HAL support, we can call nextBuffer() from here - // instead of using onFrameAvailable(). No real benefit, except it'll be - // more like VirtualDisplaySurface. - return NO_ERROR; -#endif } -#ifdef USE_HWC2 status_t FramebufferSurface::nextBuffer(uint32_t& outSlot, sp& outBuffer, sp& outFence, android_dataspace_t& outDataspace) { -#else -status_t FramebufferSurface::nextBuffer(sp& outBuffer, sp& outFence) { -#endif Mutex::Autolock lock(mMutex); BufferItem item; status_t err = acquireBufferLocked(&item, 0); if (err == BufferQueue::NO_BUFFER_AVAILABLE) { -#ifdef USE_HWC2 mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer); -#else - outBuffer = mCurrentBuffer; -#endif return NO_ERROR; } else if (err != NO_ERROR) { ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err); @@ -152,26 +126,15 @@ status_t FramebufferSurface::nextBuffer(sp& outBuffer, sp& // had released the old buffer first. if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT && item.mSlot != mCurrentBufferSlot) { -#ifdef USE_HWC2 mHasPendingRelease = true; mPreviousBufferSlot = mCurrentBufferSlot; mPreviousBuffer = mCurrentBuffer; -#else - // Release the previous buffer. - err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer, - EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); - if (err < NO_ERROR) { - ALOGE("error releasing buffer: %s (%d)", strerror(-err), err); - return err; - } -#endif } mCurrentBufferSlot = item.mSlot; mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer; mCurrentFence = item.mFence; outFence = item.mFence; -#ifdef USE_HWC2 mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer); outDataspace = item.mDataSpace; @@ -181,31 +144,10 @@ status_t FramebufferSurface::nextBuffer(sp& outBuffer, sp& ALOGE("error posting framebuffer: %d", result); return result; } -#else - outBuffer = mCurrentBuffer; -#endif return NO_ERROR; } -#ifndef USE_HWC2 -// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl. -void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) { - sp buf; - sp acquireFence; - status_t err = nextBuffer(buf, acquireFence); - if (err != NO_ERROR) { - ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)", - strerror(-err), err); - return; - } - err = mHwc.fbPost(mDisplayType, acquireFence, buf); - if (err != NO_ERROR) { - ALOGE("error posting framebuffer: %d", err); - } -} -#endif - void FramebufferSurface::freeBufferLocked(int slotIndex) { ConsumerBase::freeBufferLocked(slotIndex); if (slotIndex == mCurrentBufferSlot) { @@ -214,7 +156,6 @@ void FramebufferSurface::freeBufferLocked(int slotIndex) { } void FramebufferSurface::onFrameCommitted() { -#ifdef USE_HWC2 if (mHasPendingRelease) { sp fence = mHwc.getPresentFence(mDisplayType); if (fence->isValid()) { @@ -231,24 +172,7 @@ void FramebufferSurface::onFrameCommitted() { mPreviousBuffer.clear(); mHasPendingRelease = false; } -#else - sp fence = mHwc.getAndResetReleaseFence(mDisplayType); - if (fence->isValid() && - mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) { - status_t err = addReleaseFence(mCurrentBufferSlot, - mCurrentBuffer, fence); - ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)", - strerror(-err), err); - } -#endif -} - -#ifndef USE_HWC2 -status_t FramebufferSurface::compositionComplete() -{ - return mHwc.fbCompositionComplete(); } -#endif void FramebufferSurface::dumpAsString(String8& result) const { Mutex::Autolock lock(mMutex); @@ -259,9 +183,6 @@ void FramebufferSurface::dumpAsString(String8& result) const { void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const { -#ifndef USE_HWC2 - mHwc.fbDump(result); -#endif ConsumerBase::dumpLocked(result, prefix); } diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index a1756ca3c2..4186b7aac4 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -42,9 +42,6 @@ public: virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); -#ifndef USE_HWC2 - virtual status_t compositionComplete(); -#endif virtual status_t advanceFrame(); virtual void onFrameCommitted(); virtual void dumpAsString(String8& result) const; @@ -58,9 +55,6 @@ public: private: virtual ~FramebufferSurface() { }; // this class cannot be overloaded -#ifndef USE_HWC2 - virtual void onFrameAvailable(const BufferItem& item); -#endif virtual void freeBufferLocked(int slotIndex); virtual void dumpLocked(String8& result, const char* prefix) const; @@ -68,12 +62,8 @@ private: // nextBuffer waits for and then latches the next buffer from the // BufferQueue and releases the previously latched buffer to the // BufferQueue. The new buffer is returned in the 'buffer' argument. -#ifdef USE_HWC2 status_t nextBuffer(uint32_t& outSlot, sp& outBuffer, sp& outFence, android_dataspace_t& outDataspace); -#else - status_t nextBuffer(sp& outBuffer, sp& outFence); -#endif // mDisplayType must match one of the HWC display types int mDisplayType; @@ -100,14 +90,12 @@ private: // Hardware composer, owned by SurfaceFlinger. HWComposer& mHwc; -#ifdef USE_HWC2 HWComposerBufferCache mHwcBufferCache; // Previous buffer to release after getting an updated retire fence bool mHasPendingRelease; int mPreviousBufferSlot; sp mPreviousBuffer; -#endif }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 3640bb5a98..3b6d931b5c 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -14,10 +14,6 @@ * limitations under the License. */ -#ifndef USE_HWC2 -#include "HWComposer_hwc1.h" -#else - #ifndef ANDROID_SF_HWCOMPOSER_H #define ANDROID_SF_HWCOMPOSER_H @@ -219,5 +215,3 @@ private: }; // namespace android #endif // ANDROID_SF_HWCOMPOSER_H - -#endif // #ifdef USE_HWC2 diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 1de5e48cb9..dba6f7cf9a 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -176,12 +176,6 @@ status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) { return NO_ERROR; } -#ifndef USE_HWC2 -status_t VirtualDisplaySurface::compositionComplete() { - return NO_ERROR; -} -#endif - status_t VirtualDisplaySurface::advanceFrame() { if (mDisplayId < 0) return NO_ERROR; @@ -221,7 +215,6 @@ status_t VirtualDisplaySurface::advanceFrame() { status_t result = NO_ERROR; if (fbBuffer != NULL) { -#ifdef USE_HWC2 uint32_t hwcSlot = 0; sp hwcBuffer; mHwcBufferCache.getHwcBuffer(mFbProducerSlot, fbBuffer, @@ -230,9 +223,6 @@ status_t VirtualDisplaySurface::advanceFrame() { // TODO: Correctly propagate the dataspace from GL composition result = mHwc.setClientTarget(mDisplayId, hwcSlot, mFbFence, hwcBuffer, HAL_DATASPACE_UNKNOWN); -#else - result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer); -#endif } return result; @@ -246,22 +236,14 @@ void VirtualDisplaySurface::onFrameCommitted() { "Unexpected onFrameCommitted() in %s state", dbgStateStr()); mDbgState = DBG_STATE_IDLE; -#ifdef USE_HWC2 sp retireFence = mHwc.getPresentFence(mDisplayId); -#else - sp fbFence = mHwc.getAndResetReleaseFence(mDisplayId); -#endif if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) { // release the scratch buffer back to the pool Mutex::Autolock lock(mMutex); int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot); VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot); -#ifdef USE_HWC2 addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], retireFence); -#else - addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], fbFence); -#endif releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot], EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); } @@ -269,9 +251,6 @@ void VirtualDisplaySurface::onFrameCommitted() { if (mOutputProducerSlot >= 0) { int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot); QueueBufferOutput qbo; -#ifndef USE_HWC2 - sp outFence = mHwc.getLastRetireFence(mDisplayId); -#endif VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot); if (mMustRecompose) { status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot, @@ -280,11 +259,7 @@ void VirtualDisplaySurface::onFrameCommitted() { HAL_DATASPACE_UNKNOWN, Rect(mSinkBufferWidth, mSinkBufferHeight), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */, -#ifdef USE_HWC2 retireFence), -#else - outFence), -#endif &qbo); if (result == NO_ERROR) { updateQueueBufferOutput(std::move(qbo)); @@ -294,11 +269,7 @@ void VirtualDisplaySurface::onFrameCommitted() { // through the motions of updating the display to keep our state // machine happy. We cancel the buffer to avoid triggering another // re-composition and causing an infinite loop. -#ifdef USE_HWC2 mSource[SOURCE_SINK]->cancelBuffer(sslot, retireFence); -#else - mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence); -#endif } } diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 1671aba1d8..5c8aceae92 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -84,9 +84,6 @@ public: // virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); -#ifndef USE_HWC2 - virtual status_t compositionComplete(); -#endif virtual status_t advanceFrame(); virtual void onFrameCommitted(); virtual void dumpAsString(String8& result) const; @@ -253,10 +250,7 @@ private: bool mMustRecompose; -#ifdef USE_HWC2 HWComposerBufferCache mHwcBufferCache; -#endif - bool mForceHwcCopy; }; diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp index 052a959724..02eea4769b 100644 --- a/services/surfaceflinger/EventControlThread.cpp +++ b/services/surfaceflinger/EventControlThread.cpp @@ -53,12 +53,7 @@ bool EventControlThread::threadLoop() { } bool enable = requestedVsyncState == VsyncState::On; -#ifdef USE_HWC2 mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable); -#else - mFlinger->eventControl(HWC_DISPLAY_PRIMARY, - SurfaceFlinger::EVENT_VSYNC, enable); -#endif currentVsyncState = requestedVsyncState; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 80987a4f91..aa3100eb1d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -85,9 +85,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mFiltering(false), mNeedsFiltering(false), mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2), -#ifndef USE_HWC2 - mIsGlesComposition(false), -#endif mProtectedByApp(false), mClientRef(client), mPotentialCursor(false), @@ -128,13 +125,9 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n // drawing state & current state are identical mDrawingState = mCurrentState; -#ifdef USE_HWC2 const auto& hwc = flinger->getHwComposer(); const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY); nsecs_t displayPeriod = activeConfig->getVsyncPeriod(); -#else - nsecs_t displayPeriod = flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); -#endif mFrameTracker.setDisplayRefreshPeriod(displayPeriod); CompositorTiming compositorTiming; @@ -157,12 +150,7 @@ Layer::~Layer() { * Layer. So, the implementation is done in BufferLayer. When called on a * ColorLayer object, it's essentially a NOP. */ -#ifdef USE_HWC2 void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} -#else -void Layer::onLayerDisplayed(const sp& /* hw */, - HWComposer::HWCLayerInterface* /*layer*/) {} -#endif void Layer::onRemovedFromCurrentState() { // the layer is removed from SF mCurrentState to mLayersPendingRemoval @@ -187,9 +175,7 @@ void Layer::onRemoved() { // the layer is removed from SF mLayersPendingRemoval abandon(); -#ifdef USE_HWC2 destroyAllHwcLayers(); -#endif for (const auto& child : mCurrentChildren) { child->onRemoved(); @@ -217,7 +203,6 @@ sp Layer::getHandle() { // 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); @@ -254,7 +239,6 @@ void Layer::destroyAllHwcLayers() { 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 @@ -470,21 +454,12 @@ FloatRect Layer::computeCrop(const sp& hw) const { return crop; } -#ifdef USE_HWC2 void Layer::setGeometry(const sp& displayDevice, uint32_t z) -#else -void Layer::setGeometry(const sp& hw, HWComposer::HWCLayerInterface& layer) -#endif { -#ifdef USE_HWC2 const auto hwcId = displayDevice->getHwcDisplayId(); auto& hwcInfo = mHwcLayers[hwcId]; -#else - layer.setDefaultState(); -#endif // enable this layer -#ifdef USE_HWC2 hwcInfo.forceClientComposition = false; if (isSecure() && !displayDevice->isSecure()) { @@ -492,17 +467,9 @@ void Layer::setGeometry(const sp& hw, HWComposer::HWCLayerI } auto& hwcLayer = hwcInfo.layer; -#else - layer.setSkip(false); - - if (isSecure() && !hw->isSecure()) { - layer.setSkip(true); - } -#endif // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); -#ifdef USE_HWC2 auto blendMode = HWC2::BlendMode::None; if (!isOpaque(s) || getAlpha() != 1.0f) { blendMode = @@ -514,11 +481,6 @@ void Layer::setGeometry(const sp& hw, HWComposer::HWCLayerI " %s (%d)", mName.string(), to_string(blendMode).c_str(), to_string(error).c_str(), static_cast(error)); -#else - if (!isOpaque(s) || getAlpha() != 1.0f) { - layer.setBlending(mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE); - } -#endif // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects @@ -527,11 +489,7 @@ void Layer::setGeometry(const sp& hw, HWComposer::HWCLayerI if (!s.crop.isEmpty()) { Rect activeCrop(s.crop); activeCrop = t.transform(activeCrop); -#ifdef USE_HWC2 if (!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) { -#else - if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) { -#endif activeCrop.clear(); } activeCrop = t.inverse().transform(activeCrop, true); @@ -558,7 +516,6 @@ void Layer::setGeometry(const sp& hw, HWComposer::HWCLayerI frame.clear(); } } -#ifdef USE_HWC2 if (!frame.intersect(displayDevice->getViewport(), &frame)) { frame.clear(); } @@ -607,15 +564,6 @@ void Layer::setGeometry(const sp& hw, HWComposer::HWCLayerI error = hwcLayer->setInfo(type, appId); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), static_cast(error)); -#else - if (!frame.intersect(hw->getViewport(), &frame)) { - frame.clear(); - } - const Transform& tr(hw->getTransform()); - layer.setFrame(tr.transform(frame)); - layer.setCrop(computeCrop(hw)); - layer.setPlaneAlpha(static_cast(std::round(255.0f * getAlpha()))); -#endif /* * Transformations are applied in this order: @@ -650,7 +598,6 @@ void Layer::setGeometry(const sp& hw, HWComposer::HWCLayerI // this gives us only the "orientation" component of the transform const uint32_t orientation = transform.getOrientation(); -#ifdef USE_HWC2 if (orientation & Transform::ROT_INVALID) { // we can only handle simple transformation hwcInfo.forceClientComposition = true; @@ -663,17 +610,8 @@ void Layer::setGeometry(const sp& hw, HWComposer::HWCLayerI mName.string(), to_string(transform).c_str(), to_string(error).c_str(), static_cast(error)); } -#else - if (orientation & Transform::ROT_INVALID) { - // we can only handle simple transformation - layer.setSkip(true); - } else { - layer.setTransform(orientation); - } -#endif } -#ifdef USE_HWC2 void Layer::forceClientComposition(int32_t hwcId) { if (mHwcLayers.count(hwcId) == 0) { ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId); @@ -682,32 +620,7 @@ void Layer::forceClientComposition(int32_t hwcId) { mHwcLayers[hwcId].forceClientComposition = true; } -#else -void Layer::setPerFrameData(const sp& hw, - HWComposer::HWCLayerInterface& layer) { - // we have to set the visible region on every frame because - // we currently free it during onLayerDisplayed(), which is called - // after HWComposer::commit() -- every frame. - // Apply this display's projection's viewport to the visible region - // before giving it to the HWC HAL. - const Transform& tr = hw->getTransform(); - Region visible = tr.transform(visibleRegion.intersect(hw->getViewport())); - layer.setVisibleRegionScreen(visible); - layer.setSurfaceDamage(surfaceDamageRegion); - mIsGlesComposition = (layer.getCompositionType() == HWC_FRAMEBUFFER); - - if (mSidebandStream.get()) { - layer.setSidebandStream(mSidebandStream); - } else { - // NOTE: buffer can be NULL if the client never drew into this - // layer yet, or if we ran out of memory - layer.setBuffer(mActiveBuffer); - } -} -#endif - -#ifdef USE_HWC2 void Layer::updateCursorPosition(const sp& displayDevice) { auto hwcId = displayDevice->getHwcDisplayId(); if (mHwcLayers.count(hwcId) == 0 || getCompositionType(hwcId) != HWC2::Composition::Cursor) { @@ -740,28 +653,6 @@ void Layer::updateCursorPosition(const sp& displayDevice) { mName.string(), position.left, position.top, to_string(error).c_str(), static_cast(error)); } -#else -Rect Layer::getPosition(const sp& hw) { - // this gives us only the "orientation" component of the transform - const State& s(getCurrentState()); - - // apply the layer's transform, followed by the display's global transform - // here we're guaranteed that the layer's transform preserves rects - Rect win(s.active.w, s.active.h); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); - } - // subtract the transparent region and snap to the bounds - Rect bounds = reduce(win, s.activeTransparentRegion); - Rect frame(getTransform().transform(bounds)); - frame.intersect(hw->getViewport(), &frame); - if (!s.finalCrop.isEmpty()) { - frame.intersect(s.finalCrop, &frame); - } - const Transform& tr(hw->getTransform()); - return Rect(tr.transform(frame)); -} -#endif // --------------------------------------------------------------------------- // drawing... @@ -791,7 +682,6 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { clearWithOpenGL(renderArea, 0, 0, 0, 0); } -#ifdef USE_HWC2 void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) { if (mHwcLayers.count(hwcId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); @@ -843,7 +733,6 @@ bool Layer::getClearClientTarget(int32_t hwcId) const { } return mHwcLayers.at(hwcId).clearClientTarget; } -#endif bool Layer::addSyncPoint(const std::shared_ptr& point) { if (point->getFrameNumber() <= mCurrentFrameNumber) { @@ -1496,7 +1385,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mContentDirty = contentDirty; return info; } -#ifdef USE_HWC2 + void Layer::miniDumpHeader(String8& result) { result.append("----------------------------------------"); result.append("---------------------------------------\n"); @@ -1539,7 +1428,6 @@ void Layer::miniDump(String8& result, int32_t hwcId) const { result.append("- - - - - - - - - - - - - - - - - - - - "); result.append("- - - - - - - - - - - - - - - - - - - -\n"); } -#endif void Layer::dumpFrameStats(String8& result) const { mFrameTracker.dumpStats(result); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 0580b9f40f..c125a3c3e1 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -297,7 +297,6 @@ protected: public: virtual void setDefaultBufferSize(uint32_t w, uint32_t h) = 0; -#ifdef USE_HWC2 void setGeometry(const sp& displayDevice, uint32_t z); void forceClientComposition(int32_t hwcId); virtual void setPerFrameData(const sp& displayDevice) = 0; @@ -309,23 +308,11 @@ public: void setClearClientTarget(int32_t hwcId, bool clear); bool getClearClientTarget(int32_t hwcId) const; void updateCursorPosition(const sp& hw); -#else - void setGeometry(const sp& hw, HWComposer::HWCLayerInterface& layer); - void setPerFrameData(const sp& hw, HWComposer::HWCLayerInterface& layer); - virtual void setAcquireFence(const sp& hw, - HWComposer::HWCLayerInterface& layer) = 0; - Rect getPosition(const sp& hw); -#endif /* * called after page-flip */ -#ifdef USE_HWC2 virtual void onLayerDisplayed(const sp& releaseFence); -#else - virtual void onLayerDisplayed(const sp& hw, - HWComposer::HWCLayerInterface* layer); -#endif virtual void abandon() = 0; @@ -346,10 +333,8 @@ public: const std::shared_ptr& presentFence, const CompositorTiming& compositorTiming) = 0; -#ifdef USE_HWC2 // If a buffer was replaced this frame, release the former buffer virtual void releasePendingBuffer(nsecs_t dequeueReadyTime) = 0; -#endif /* * draw - performs some global clipping optimizations @@ -425,7 +410,6 @@ public: int32_t getQueuedFrameCount() const { return mQueuedFrames; } -#ifdef USE_HWC2 // ----------------------------------------------------------------------- bool createHwcLayer(HWComposer* hwc, int32_t hwcId); @@ -441,7 +425,6 @@ public: return mHwcLayers[hwcId].layer; } -#endif // ----------------------------------------------------------------------- void clearWithOpenGL(const RenderArea& renderArea) const; @@ -458,10 +441,8 @@ public: LayerDebugInfo getLayerDebugInfo() const; /* always call base class first */ -#ifdef USE_HWC2 static void miniDumpHeader(String8& result); void miniDump(String8& result, int32_t hwcId) const; -#endif void dumpFrameStats(String8& result) const; void dumpFrameEvents(String8& result); void clearFrameStats(); @@ -673,7 +654,6 @@ protected: bool mPendingRemoval = false; -#ifdef USE_HWC2 // HWC items, accessed from the main thread struct HWCInfo { HWCInfo() @@ -698,9 +678,6 @@ protected: // case we need to keep track. In non-mirror mode, a layer will have only one // HWCInfo. This map key is a display layerStack. std::unordered_map mHwcLayers; -#else - bool mIsGlesComposition; -#endif // page-flip thread (currently main thread) bool mProtectedByApp; // application requires protected path to external sink diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index faf1ec64f8..44b9dc9254 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -24,10 +24,8 @@ public: int getReqHeight() const { return mReqHeight; }; int getReqWidth() const { return mReqWidth; }; Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; -#ifdef USE_HWC2 virtual bool getWideColorSupport() const = 0; virtual android_color_mode_t getActiveColorMode() const = 0; -#endif status_t updateDimensions(); @@ -37,4 +35,4 @@ private: Transform::orientation_flags mRotationFlags; }; -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index daaa11e1d3..3ae7042230 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -44,7 +44,6 @@ #include // --------------------------------------------------------------------------- -#ifdef USE_HWC2 bool checkGlError(const char* op, int lineNumber) { bool errorFound = false; GLint error = glGetError(); @@ -103,7 +102,6 @@ void writePPM(const char* basename, GLuint width, GLuint height) { } file.write(reinterpret_cast(outBuffer.data()), outBuffer.size()); } -#endif // --------------------------------------------------------------------------- namespace android { @@ -132,7 +130,6 @@ GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) : //mColorBlindnessCorrection = M; -#ifdef USE_HWC2 if (mPlatformHasWideColor) { // Compute sRGB to DisplayP3 color transform // NOTE: For now, we are limiting wide-color support to @@ -145,7 +142,6 @@ GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) : mat4 gamutTransform(srgbToP3); mSrgbToDisplayP3 = gamutTransform; } -#endif } GLES20RenderEngine::~GLES20RenderEngine() { @@ -222,7 +218,6 @@ void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, } } -#ifdef USE_HWC2 void GLES20RenderEngine::setColorMode(android_color_mode mode) { ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode); @@ -256,7 +251,6 @@ void GLES20RenderEngine::setWideColor(bool hasWideColor) { bool GLES20RenderEngine::usesWideColor() { return mUseWideColor; } -#endif void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) { GLuint target = texture.getTextureTarget(); @@ -344,7 +338,6 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { mesh.getByteStride(), mesh.getPositions()); -#ifdef USE_HWC2 if (usesWideColor()) { Description wideColorState = mState; if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) { @@ -366,11 +359,6 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); } -#else - ProgramCache::getInstance().useProgram(mState); - - glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); -#endif if (mesh.getTexCoordsSize()) { glDisableVertexAttribArray(Program::texCoords); @@ -379,13 +367,11 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { void GLES20RenderEngine::dump(String8& result) { RenderEngine::dump(result); -#ifdef USE_HWC2 if (usesWideColor()) { result.append("Wide-color: On\n"); } else { result.append("Wide-color: Off\n"); } -#endif } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index 5ac12fc3d6..b96bfe0f99 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -70,7 +70,6 @@ protected: Transform::orientation_flags rotation); virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, const half4& color) override; -#ifdef USE_HWC2 // Color management related functions and state void setColorMode(android_color_mode mode); @@ -91,7 +90,6 @@ protected: // Currently only supporting sRGB and DisplayP3 color spaces mat4 mSrgbToDisplayP3; -#endif bool mPlatformHasWideColor = false; virtual void setupLayerTexturing(const Texture& texture); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index fa65979edd..7e05cec7d6 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -101,12 +101,10 @@ public: Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation) = 0; virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, const half4& color) = 0; -#ifdef USE_HWC2 virtual void setColorMode(android_color_mode mode) = 0; virtual void setSourceDataSpace(android_dataspace source) = 0; virtual void setWideColor(bool hasWideColor) = 0; virtual bool usesWideColor() = 0; -#endif virtual void setupLayerTexturing(const Texture& texture) = 0; virtual void setupLayerBlackedOut() = 0; virtual void setupFillWithColor(float r, float g, float b, float a) = 0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d13b188ab8..96ba5fb766 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2675,12 +2675,10 @@ bool SurfaceFlinger::doComposeSurfaces( if (hasClientComposition) { ALOGV("hasClientComposition"); -#ifdef USE_HWC2 mRenderEngine->setWideColor( displayDevice->getWideColorSupport() && !mForceNativeColorMode); mRenderEngine->setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode()); -#endif if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", displayDevice->getDisplayName().string()); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d10b41bd34..67e4607012 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -63,12 +63,8 @@ #include "SurfaceTracing.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" @@ -117,11 +113,7 @@ enum { class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, private IBinder::DeathRecipient, -#ifdef USE_HWC2 private HWC2::ComposerCallback -#else - private HWComposer::EventHandler -#endif { public: @@ -217,11 +209,7 @@ public: // enable/disable h/w composer event // TODO: this should be made accessible only to EventThread -#ifdef USE_HWC2 void setVsyncEnabled(int disp, int enabled); -#else - void eventControl(int disp, int event, int enabled); -#endif // called on the main thread by MessageQueue when an internal message // is received @@ -344,18 +332,12 @@ private: /* ------------------------------------------------------------------------ * HWC2::ComposerCallback / HWComposer::EventHandler interface */ -#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 @@ -372,12 +354,8 @@ private: // called on the main thread in response to setActiveConfig() void setActiveConfigInternal(const sp& hw, int mode); // called on the main thread in response to setPowerMode() -#ifdef USE_HWC2 void setPowerModeInternal(const sp& hw, int mode, bool stateLockHeld); -#else - void setPowerModeInternal(const sp& hw, int mode); -#endif // Called on the main thread in response to setActiveColorMode() void setActiveColorModeInternal(const sp& hw, android_color_mode_t colorMode); @@ -463,17 +441,10 @@ private: const sp& producer, bool useIdentityTransform); -#ifdef USE_HWC2 status_t captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, bool isLocalScreenshot, int* outSyncFd); -#else - status_t captureScreenImplLocked(const RenderArea& renderArea, - TraverseLayersFunction traverseLayers, - const sp& producer, - bool useIdentityTransform, bool isLocalScreenshot); -#endif void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor); @@ -540,10 +511,6 @@ private: // region of all screens presenting this layer stack. void invalidateLayerStack(const sp& layer, const Region& dirty); -#ifndef USE_HWC2 - int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type); -#endif - /* ------------------------------------------------------------------------ * H/W composer */ @@ -642,7 +609,6 @@ private: } status_t doDump(int fd, const Vector& args, bool asProto); -#ifdef USE_HWC2 /* ------------------------------------------------------------------------ * VrFlinger */ @@ -650,7 +616,6 @@ private: // Check to see if we should handoff to vr flinger. void updateVrFlinger(); -#endif /* ------------------------------------------------------------------------ * Attributes @@ -695,9 +660,7 @@ private: // acquiring mStateLock. std::unique_ptr mHwc; -#ifdef USE_HWC2 const std::string mHwcServiceName; // "default" for real use, something else for testing. -#endif // constant members (no synchronization needed for access) RenderEngine* mRenderEngine; @@ -716,17 +679,11 @@ private: // don't need synchronization State mDrawingState{LayerVector::StateSet::Drawing}; bool mVisibleRegionsDirty; -#ifndef USE_HWC2 - bool mHwWorkListDirty; -#else bool mGeometryInvalid; -#endif bool mAnimCompositionPending; -#ifdef USE_HWC2 std::vector> mLayersWithQueuedFrames; sp mPreviousPresentFence = Fence::NO_FENCE; bool mHadClientComposition = false; -#endif FenceTimeline mGlCompositionDoneTimeline; FenceTimeline mDisplayTimeline; @@ -745,9 +702,7 @@ private: nsecs_t mLastTransactionTime; bool mBootFinished; bool mForceFullDamage; -#ifdef USE_HWC2 bool mPropagateBackpressure = true; -#endif SurfaceInterceptor mInterceptor; SurfaceTracing mTracing; bool mUseHwcVirtualDisplays = false; @@ -789,9 +744,6 @@ private: bool mInjectVSyncs; Daltonizer mDaltonizer; -#ifndef USE_HWC2 - bool mDaltonize; -#endif mat4 mPreviousColorMatrix; mat4 mColorMatrix; @@ -833,7 +785,6 @@ private: // either AID_GRAPHICS or AID_SYSTEM. status_t CheckTransactCodeCredentials(uint32_t code); -#ifdef USE_HWC2 std::unique_ptr mVrFlinger; std::atomic mVrFlingerRequestsDisplay; static bool useVrFlinger; @@ -842,7 +793,6 @@ private: // 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; bool mForceNativeColorMode = false; diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp index abc8fde26b..e17bb58b31 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp @@ -89,11 +89,7 @@ status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter, } // Release the previous buffer. -#ifdef USE_HWC2 err = updateAndReleaseLocked(item, &mPendingRelease); -#else - err = updateAndReleaseLocked(item); -#endif if (err != NO_ERROR) { return err; } @@ -197,7 +193,6 @@ sp SurfaceFlingerConsumer::getPrevFinalReleaseFence() const { return ConsumerBase::mPrevFinalReleaseFence; } -#ifdef USE_HWC2 void SurfaceFlingerConsumer::setReleaseFence(const sp& fence) { if (!mPendingRelease.isPending) { @@ -230,7 +225,6 @@ bool SurfaceFlingerConsumer::releasePendingBuffer() mPendingRelease = PendingRelease(); return true; } -#endif void SurfaceFlingerConsumer::setContentsChangedListener( const wp& listener) { diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h index 1126233d60..53b4915426 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -81,10 +81,8 @@ public: nsecs_t computeExpectedPresent(const DispSync& dispSync); sp getPrevFinalReleaseFence() const; -#ifdef USE_HWC2 virtual void setReleaseFence(const sp& fence) override; bool releasePendingBuffer(); -#endif void onDisconnect() override; void addAndGetFrameTimestamps( @@ -104,11 +102,9 @@ private: // The portion of this surface that has changed since the previous frame Region mSurfaceDamage; -#ifdef USE_HWC2 // A release that is pending on the receipt of a new release fence from // presentDisplay PendingRelease mPendingRelease; -#endif // The layer for this SurfaceFlingerConsumer const wp mLayer; diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h index 2a5a8ad03f..b94418281e 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h @@ -16,7 +16,11 @@ #pragma once +#define HWC2_USE_CPP11 +#define HWC2_INCLUDE_STRINGIFICATION #include "ComposerClient.h" +#undef HWC2_USE_CPP11 +#undef HWC2_INCLUDE_STRINGIFICATION #include "RenderState.h" // Needed for display type/ID enums -- cgit v1.2.3-59-g8ed1b From c9232edd34618360d099272fb0537cae2f715860 Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 14 Nov 2017 15:31:15 -0800 Subject: Added check for forceClientComposition for every layer. Instead of having the Layers check for forceClientComposition, have SurfaceFlinger check since it will be skipping hwc. This also ensures that new Layer types also get the same check. Fixes: 69254085 Test: Current tests pass. Rotation works correctly now. Change-Id: I7a2a378d9690206008b1dab9ce521f959542903a --- services/surfaceflinger/BufferLayer.cpp | 8 -------- services/surfaceflinger/Layer.cpp | 9 +++++++++ services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 6 ++++++ 4 files changed, 16 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 0c1693b53b..c477a3b190 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -613,14 +613,6 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) return; } - // Client layers - if (hwcInfo.forceClientComposition || - (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) { - ALOGV("[%s] Requesting Client composition", mName.string()); - setCompositionType(hwcId, HWC2::Composition::Client); - return; - } - // Device or Cursor layers if (mPotentialCursor) { ALOGV("[%s] Requesting Cursor composition", mName.string()); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index aa3100eb1d..50e2c6f55c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -621,6 +621,15 @@ void Layer::forceClientComposition(int32_t hwcId) { mHwcLayers[hwcId].forceClientComposition = true; } +bool Layer::getForceClientComposition(int32_t hwcId) { + if (mHwcLayers.count(hwcId) == 0) { + ALOGE("getForceClientComposition: no HWC layer found (%d)", hwcId); + return false; + } + + return mHwcLayers[hwcId].forceClientComposition; +} + void Layer::updateCursorPosition(const sp& displayDevice) { auto hwcId = displayDevice->getHwcDisplayId(); if (mHwcLayers.count(hwcId) == 0 || getCompositionType(hwcId) != HWC2::Composition::Cursor) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index c125a3c3e1..0fc5ad55d2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -299,6 +299,7 @@ public: void setGeometry(const sp& displayDevice, uint32_t z); void forceClientComposition(int32_t hwcId); + bool getForceClientComposition(int32_t hwcId); virtual void setPerFrameData(const sp& displayDevice) = 0; // callIntoHwc exists so we can update our local state and call diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 96ba5fb766..1237ee4320 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1956,6 +1956,12 @@ void SurfaceFlinger::setUpHWComposer() { "display %zd: %d", displayId, result); } for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + if (layer->getForceClientComposition(hwcId)) { + ALOGV("[%s] Requesting Client composition", layer->getName().string()); + layer->setCompositionType(hwcId, HWC2::Composition::Client); + continue; + } + layer->setPerFrameData(displayDevice); } -- cgit v1.2.3-59-g8ed1b From 8e0af3679ec73e07775142825d592448b255f61c Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Tue, 14 Nov 2017 16:28:28 +0100 Subject: Trace drawing state Some state that was dumped was still the current state, creating misalignment between what was visible on screen and what was being dumped. Make sure to dump all state consistently. Test: adb shell service call SurfaceFlinger 1025 i32 1 && adb shell service call SurfaceFlinger 1025 i32 0 && adb pull /data/misc/trace/layerstrace.pb Inspect with WindowScope Change-Id: I16ea06764328fd8c506ed90dfc59929f7d26d156 --- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 14 ++++++++------ services/surfaceflinger/SurfaceFlinger.h | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index aa3100eb1d..f5fb109ae6 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1786,7 +1786,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform()); LayerProtoHelper::writeToProto(requestedTransform, layerInfo->mutable_requested_transform()); - auto parent = getParent(); + auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote(); if (parent != nullptr) { layerInfo->set_parent(parent->sequence); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 96ba5fb766..9e7563c594 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1585,7 +1585,7 @@ void SurfaceFlinger::doTracing(const char* where) { ATRACE_CALL(); ATRACE_NAME(where); if (CC_UNLIKELY(mTracing.isEnabled())) { - mTracing.traceLayers(where, dumpProtoInfo()); + mTracing.traceLayers(where, dumpProtoInfo(LayerVector::StateSet::Drawing)); } } @@ -3534,7 +3534,7 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro size_t numArgs = args.size(); if (asProto) { - LayersProto layersProto = dumpProtoInfo(); + LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); dumpAll = false; } @@ -3783,11 +3783,13 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { result.append("\n"); } -LayersProto SurfaceFlinger::dumpProtoInfo() const { +LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const { LayersProto layersProto; - mCurrentState.traverseInZOrder([&](Layer* layer) { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const State& state = useDrawing ? mDrawingState : mCurrentState; + state.traverseInZOrder([&](Layer* layer) { LayerProto* layerProto = layersProto.add_layers(); - layer->writeToProto(layerProto, LayerVector::StateSet::Current); + layer->writeToProto(layerProto, stateSet); }); return layersProto; @@ -3858,7 +3860,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, result.appendFormat("Visible layers (count = %zu)\n", mNumLayers); colorizer.reset(result); - LayersProto layersProto = dumpProtoInfo(); + LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); auto layerTree = LayerProtoParser::generateLayerTree(layersProto); result.append(LayerProtoParser::layersToString(layerTree).c_str()); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 67e4607012..386d42bef1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -602,7 +602,7 @@ private: std::vector&& history); void dumpBufferingStats(String8& result) const; void dumpWideColorInfo(String8& result) const; - LayersProto dumpProtoInfo() const; + LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const; bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; -- cgit v1.2.3-59-g8ed1b From 503c7046237f2797a5cf8584064223359d0e6d10 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 27 Sep 2017 15:06:08 -0700 Subject: Allow relative layering of children Initially we had hoped not to go down this route in order to produce the most understandable model, but in the end it seems to be the most sane way to satisfy some existing use cases from the WM. In particular we have the use case of the IME. The IME may of course be larger than the application it is targetting, in particular we see this in side by side split-screen portrait and freeform. However, various UI features such as the text drag handles, spell checking popups, etc, are controlled by the application process and modelled as child windows of the application. This is a good fit for them as they need to inherit most properties of the application window: Cropping, Transform, Alpha. However they need to appear over the IME! As the IME can't be a child of the application (it is bigger), we now see our use case for relative layering. Perhaps the drag handles could be reimplemented as controlled by the IME process but if nothing else as a legacy API we have exposed the idea of child windows of the app going over the IME and are likely to need to continue to support it in some mode. Test: Transaction_test.cpp Change-Id: If2d831bcbe88fc753b02c044a57882cca6ccffbb --- services/surfaceflinger/Layer.cpp | 21 +++++++++++++++++---- services/surfaceflinger/Layer.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 20 +++++++++++++++----- services/surfaceflinger/tests/Transaction_test.cpp | 21 +++++++++++++++++++++ 4 files changed, 55 insertions(+), 9 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 50e2c6f55c..07fc0b3122 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1100,6 +1100,19 @@ bool Layer::setChildLayer(const sp& childLayer, int32_t z) { return true; } +bool Layer::setChildRelativeLayer(const sp& childLayer, + const sp& relativeToHandle, int32_t relativeZ) { + ssize_t idx = mCurrentChildren.indexOf(childLayer); + if (idx < 0) { + return false; + } + if (childLayer->setRelativeLayer(relativeToHandle, relativeZ)) { + mCurrentChildren.removeAt(idx); + mCurrentChildren.add(childLayer); + } + return true; +} + bool Layer::setLayer(int32_t z) { if (mCurrentState.z == z) return false; mCurrentState.sequence++; @@ -1601,11 +1614,7 @@ __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::mak const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; - if (state.zOrderRelatives.size() == 0) { - return children; - } LayerVector traverse; - for (const wp& weakRelative : state.zOrderRelatives) { sp strongRelative = weakRelative.promote(); if (strongRelative != nullptr) { @@ -1614,6 +1623,10 @@ __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::mak } for (const sp& child : children) { + const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState; + if (childState.zOrderRelativeOf != nullptr) { + continue; + } traverse.add(child); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 0fc5ad55d2..bffa0c797d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -482,6 +482,8 @@ public: bool hasParent() const { return getParent() != nullptr; } Rect computeScreenBounds(bool reduceTransparentRegion = true) const; bool setChildLayer(const sp& childLayer, int32_t z); + bool setChildRelativeLayer(const sp& childLayer, + const sp& relativeToHandle, int32_t relativeZ); // Copy the current list of children to the drawing state. Called by // SurfaceFlinger to complete a transaction. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1237ee4320..1085e74e14 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3107,11 +3107,21 @@ uint32_t SurfaceFlinger::setClientStateLocked( } } if (what & layer_state_t::eRelativeLayerChanged) { - ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) { - mCurrentState.layersSortedByZ.removeAt(idx); - mCurrentState.layersSortedByZ.add(layer); - flags |= eTransactionNeeded|eTraversalNeeded; + // NOTE: index needs to be calculated before we update the state + const auto& p = layer->getParent(); + if (p == nullptr) { + ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); + if (layer->setRelativeLayer(s.relativeLayerHandle, s.z) && idx >= 0) { + mCurrentState.layersSortedByZ.removeAt(idx); + mCurrentState.layersSortedByZ.add(layer); + // we need traversal (state changed) + // AND transaction (list changed) + flags |= eTransactionNeeded|eTraversalNeeded; + } + } else { + if (p->setChildRelativeLayer(layer, s.relativeLayerHandle, s.z)) { + flags |= eTransactionNeeded|eTraversalNeeded; + } } } if (what & layer_state_t::eSizeChanged) { diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 16a16a53b1..90d48b9ee0 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1413,6 +1413,27 @@ TEST_F(ChildLayerTest, NestedChildren) { } } +TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { + sp relative = mComposerClient->createSurface(String8("Relative surface"), + 128, 128, PIXEL_FORMAT_RGBA_8888, 0); + fillSurfaceRGBA8(relative, 255, 255, 255); + + Transaction t; + t.setLayer(relative, INT32_MAX) + .setRelativeLayer(mChild, relative->getHandle(), 1) + .setPosition(mFGSurfaceControl, 0, 0) + .apply(true); + + // We expect that the child should have been elevated above our + // INT_MAX layer even though it's not a child of it. + { + ScreenCapture::captureScreen(&mCapture); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(9, 9); + mCapture->checkPixel(10, 10, 255, 255, 255); + } +} + class LayerColorTest : public LayerUpdateTest { protected: void SetUp() override { -- cgit v1.2.3-59-g8ed1b From 83806897c6366d841971a38f4a007bb83a7afb64 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 16 Nov 2017 10:50:20 -0800 Subject: surfaceflinger: fix fencing when layers become invisible A layer always holds on to a buffer (after the first one is acquired). When a new buffer comes in, and the layer is visible, it will - acquire the new buffer - present the new buffer to HWC - get the release fence from HWC - associate the old buffer with the release fence and release it But if the layer happens to be becoming invisible, it will go through - acquire the new buffer - destroy the HWC layer and present - release the old buffer without any fence The problem here is that the old buffer is still on screen until the present takes effect (e.g., on next HW vsync). Rendering artifacts may be seen on screen. This commit changes the acquire/release process for layer becoming invisible to - acquire the new buffer - destroy the HWC layer and present - get a fence from HWC - associate the old buffer with the fence and release it We do not require HWC getReleaseFences to return fences for destroyed layers. We can only use the next best fence, the present fence. Bug: 68490054 Test: manual Change-Id: I68bbf392a6681c6512fc0be68a7d17df122f7308 --- services/surfaceflinger/BufferLayer.cpp | 3 --- services/surfaceflinger/DisplayDevice.cpp | 8 ++++++++ services/surfaceflinger/DisplayDevice.h | 4 ++++ services/surfaceflinger/Layer.cpp | 6 ++++-- services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 31 ++++++++++++++++++++++++++++-- 6 files changed, 46 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index c477a3b190..4e214d1b74 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -262,9 +262,6 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, } void BufferLayer::onLayerDisplayed(const sp& releaseFence) { - if (mHwcLayers.empty()) { - return; - } mSurfaceFlingerConsumer->setReleaseFence(releaseFence); } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index ef7d482f28..6d6781e4d4 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -325,6 +325,14 @@ const Vector< sp >& DisplayDevice::getVisibleLayersSortedByZ() const { return mVisibleLayersSortedByZ; } +void DisplayDevice::setLayersNeedingFences(const Vector< sp >& layers) { + mLayersNeedingFences = layers; +} + +const Vector< sp >& DisplayDevice::getLayersNeedingFences() const { + return mLayersNeedingFences; +} + Region DisplayDevice::getDirtyRegion(bool repaintEverything) const { Region dirty; if (repaintEverything) { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 50e30b2571..e388a5b2c3 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -113,6 +113,8 @@ public: void setVisibleLayersSortedByZ(const Vector< sp >& layers); const Vector< sp >& getVisibleLayersSortedByZ() const; + void setLayersNeedingFences(const Vector< sp >& layers); + const Vector< sp >& getLayersNeedingFences() const; Region getDirtyRegion(bool repaintEverything) const; void setLayerStack(uint32_t stack); @@ -214,6 +216,8 @@ private: // list of visible layers on that display Vector< sp > mVisibleLayersSortedByZ; + // list of layers needing fences + Vector< sp > mLayersNeedingFences; /* * Transaction state diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 50e2c6f55c..abf25ec117 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -217,9 +217,9 @@ bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) { return true; } -void Layer::destroyHwcLayer(int32_t hwcId) { +bool Layer::destroyHwcLayer(int32_t hwcId) { if (mHwcLayers.count(hwcId) == 0) { - return; + return false; } auto& hwcInfo = mHwcLayers[hwcId]; LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer"); @@ -228,6 +228,8 @@ void Layer::destroyHwcLayer(int32_t hwcId) { // 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"); + + return true; } void Layer::destroyAllHwcLayers() { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 0fc5ad55d2..44b178a71b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -414,7 +414,7 @@ public: // ----------------------------------------------------------------------- bool createHwcLayer(HWComposer* hwc, int32_t hwcId); - void destroyHwcLayer(int32_t hwcId); + bool destroyHwcLayer(int32_t hwcId); void destroyAllHwcLayers(); bool hasHwcLayer(int32_t hwcId) { return mHwcLayers.count(hwcId) > 0; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1237ee4320..4e73bfa6b7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1781,6 +1781,7 @@ void SurfaceFlinger::rebuildLayerStacks() { Region opaqueRegion; Region dirtyRegion; Vector> layersSortedByZ; + Vector> layersNeedingFences; const sp& displayDevice(mDisplays[dpy]); const Transform& tr(displayDevice->getTransform()); const Rect bounds(displayDevice->getBounds()); @@ -1788,6 +1789,7 @@ void SurfaceFlinger::rebuildLayerStacks() { computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion); mDrawingState.traverseInZOrder([&](Layer* layer) { + bool hwcLayerDestroyed = false; if (layer->belongsToDisplay(displayDevice->getLayerStack(), displayDevice->isPrimary())) { Region drawRegion(tr.transform( @@ -1798,18 +1800,32 @@ void SurfaceFlinger::rebuildLayerStacks() { } else { // Clear out the HWC layer if this layer was // previously visible, but no longer is - layer->destroyHwcLayer( + hwcLayerDestroyed = 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->destroyHwcLayer(displayDevice->getHwcDisplayId()); + hwcLayerDestroyed = layer->destroyHwcLayer( + displayDevice->getHwcDisplayId()); + } + + // If a layer is not going to get a release fence because + // it is invisible, but it is also going to release its + // old buffer, add it to the list of layers needing + // fences. + if (hwcLayerDestroyed) { + auto found = std::find(mLayersWithQueuedFrames.cbegin(), + mLayersWithQueuedFrames.cend(), layer); + if (found != mLayersWithQueuedFrames.cend()) { + layersNeedingFences.add(layer); + } } }); } displayDevice->setVisibleLayersSortedByZ(layersSortedByZ); + displayDevice->setLayersNeedingFences(layersNeedingFences); displayDevice->undefinedRegion.set(bounds); displayDevice->undefinedRegion.subtractSelf( tr.transform(opaqueRegion)); @@ -2046,6 +2062,17 @@ void SurfaceFlinger::postFramebuffer() } layer->onLayerDisplayed(releaseFence); } + + // We've got a list of layers needing fences, that are disjoint with + // displayDevice->getVisibleLayersSortedByZ. The best we can do is to + // supply them with the present fence. + if (!displayDevice->getLayersNeedingFences().isEmpty()) { + sp presentFence = mHwc->getPresentFence(hwcId); + for (auto& layer : displayDevice->getLayersNeedingFences()) { + layer->onLayerDisplayed(presentFence); + } + } + if (hwcId >= 0) { mHwc->clearReleaseFences(hwcId); } -- cgit v1.2.3-59-g8ed1b From ec2d9855acb6b2dd4507bca28eaf3c5b41573c44 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 21 Nov 2017 09:21:01 -0800 Subject: surfaceflinger: fix traverseLayersInDisplay Ignore top-level relative layers in the loop since they are and should be traversed by Layer::traverseInZOrder. Test: SurfaceFlinger_test Change-Id: Ibd82298257b057b564e4985686d40c10f618e1d9 --- services/surfaceflinger/SurfaceFlinger.cpp | 3 ++- services/surfaceflinger/tests/Transaction_test.cpp | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4c03112984..ec2a459fb2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4762,7 +4762,8 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, continue; } const Layer::State& state(layer->getDrawingState()); - if (state.z < minLayerZ || state.z > maxLayerZ) { + // relative layers are traversed in Layer::traverseInZOrder + if (state.zOrderRelativeOf != nullptr || state.z < minLayerZ || state.z > maxLayerZ) { continue; } layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index ba34fe5cb3..6ede562018 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -702,6 +702,26 @@ TEST_F(LayerTransactionTest, SetRelativeZBasic) { } } +TEST_F(LayerTransactionTest, SetRelativeZNegative) { + sp layerR; + sp layerG; + sp layerB; + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED)); + ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN)); + ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE)); + + // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2 + Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply(); + + sp screenshot; + // only layerB is in this range + ScreenCapture::captureScreen(&screenshot, -2, -1); + screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); +} + TEST_F(LayerTransactionTest, SetRelativeZGroup) { sp layerR; sp layerG; -- cgit v1.2.3-59-g8ed1b From 6e8f706c21a01d6a1225e86972ff432bba5f0106 Mon Sep 17 00:00:00 2001 From: Steven Thomas Date: Wed, 22 Nov 2017 14:15:29 -0800 Subject: Fix usage of HWC_DISPLAY_PRIMARY in vr flinger The hardware composer functions require display ids obtained from the onHotplug() composer callback. Our vr flinger code was supplying HWC_DISPLAY_PRIMARY as the primary display id, which is incorrect. The HWC_DISPLAY_* values are used for representing the display type, not the display id. The code worked anyway because most hardware composers always use 0 as the primary display id, which happens to be the same value as HWC_DISPLAY_PRIMARY. The emulator uses 1 as the primary display id though, which exposed the bug. This CL changes the vr flinger code to get the display id from the onHotplug() composer callback, and uses that value when talking to hardware composer, instead of HWC_DISPLAY_PRIMARY. This matches the behavior of surface flinger. Bug: 69631196 Test: Verified the vr flinger code path works as expected on phones and standalones. Change-Id: Ia691941d0eafaa1f89e0ee81a4ae27fdef5a57cf --- libs/vr/libvrflinger/display_service.cpp | 4 +- libs/vr/libvrflinger/display_service.h | 1 + libs/vr/libvrflinger/hardware_composer.cpp | 118 ++++++++++----------- libs/vr/libvrflinger/hardware_composer.h | 28 +++-- libs/vr/libvrflinger/include/dvr/vr_flinger.h | 11 +- libs/vr/libvrflinger/vr_flinger.cpp | 12 ++- libs/vr/libvrflinger/vsync_service.cpp | 16 ++- libs/vr/libvrflinger/vsync_service.h | 7 +- services/surfaceflinger/Android.mk | 2 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 8 ++ .../surfaceflinger/DisplayHardware/HWComposer.h | 3 + services/surfaceflinger/SurfaceFlinger.cpp | 3 +- services/surfaceflinger/tests/fakehwc/Android.bp | 3 + 13 files changed, 122 insertions(+), 94 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp index ac68a5e3a4..a18ff1ac8a 100644 --- a/libs/vr/libvrflinger/display_service.cpp +++ b/libs/vr/libvrflinger/display_service.cpp @@ -38,10 +38,12 @@ namespace android { namespace dvr { DisplayService::DisplayService(Hwc2::Composer* hidl, + hwc2_display_t primary_display_id, RequestDisplayCallback request_display_callback) : BASE("DisplayService", Endpoint::Create(display::DisplayProtocol::kClientPath)) { - hardware_composer_.Initialize(hidl, request_display_callback); + hardware_composer_.Initialize( + hidl, primary_display_id, request_display_callback); } bool DisplayService::IsInitialized() const { diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h index 55e33ab852..a3ee7bb121 100644 --- a/libs/vr/libvrflinger/display_service.h +++ b/libs/vr/libvrflinger/display_service.h @@ -81,6 +81,7 @@ class DisplayService : public pdx::ServiceBase { using RequestDisplayCallback = std::function; DisplayService(android::Hwc2::Composer* hidl, + hwc2_display_t primary_display_id, RequestDisplayCallback request_display_callback); pdx::Status OnGetGlobalBuffer( diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp index 44be0ab56e..be17ecfa82 100644 --- a/libs/vr/libvrflinger/hardware_composer.cpp +++ b/libs/vr/libvrflinger/hardware_composer.cpp @@ -121,7 +121,8 @@ HardwareComposer::~HardwareComposer(void) { } bool HardwareComposer::Initialize( - Hwc2::Composer* composer, RequestDisplayCallback request_display_callback) { + Hwc2::Composer* composer, hwc2_display_t primary_display_id, + RequestDisplayCallback request_display_callback) { if (initialized_) { ALOGE("HardwareComposer::Initialize: already initialized."); return false; @@ -134,7 +135,7 @@ bool HardwareComposer::Initialize( HWC::Error error = HWC::Error::None; Hwc2::Config config; - error = composer->getActiveConfig(HWC_DISPLAY_PRIMARY, &config); + error = composer->getActiveConfig(primary_display_id, &config); if (error != HWC::Error::None) { ALOGE("HardwareComposer: Failed to get current display config : %d", @@ -142,7 +143,7 @@ bool HardwareComposer::Initialize( return false; } - error = GetDisplayMetrics(composer, HWC_DISPLAY_PRIMARY, config, + error = GetDisplayMetrics(composer, primary_display_id, config, &native_display_metrics_); if (error != HWC::Error::None) { @@ -233,7 +234,10 @@ void HardwareComposer::OnPostThreadResumed() { composer_.reset(new Hwc2::Composer("default")); composer_callback_ = new ComposerCallback; composer_->registerCallback(composer_callback_); + LOG_ALWAYS_FATAL_IF(!composer_callback_->HasDisplayId(), + "Registered composer callback but didn't get primary display"); Layer::SetComposer(composer_.get()); + Layer::SetDisplayId(composer_callback_->GetDisplayId()); } else { SetPowerMode(true); } @@ -263,6 +267,7 @@ void HardwareComposer::OnPostThreadPaused() { composer_callback_ = nullptr; composer_.reset(nullptr); Layer::SetComposer(nullptr); + Layer::SetDisplayId(0); } else { SetPowerMode(false); } @@ -290,7 +295,7 @@ HWC::Error HardwareComposer::Validate(hwc2_display_t display) { HWC::Error HardwareComposer::EnableVsync(bool enabled) { return composer_->setVsyncEnabled( - HWC_DISPLAY_PRIMARY, + composer_callback_->GetDisplayId(), (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE : HWC2_VSYNC_DISABLE)); } @@ -298,7 +303,8 @@ HWC::Error HardwareComposer::EnableVsync(bool enabled) { HWC::Error HardwareComposer::SetPowerMode(bool active) { HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off; return composer_->setPowerMode( - HWC_DISPLAY_PRIMARY, power_mode.cast()); + composer_callback_->GetDisplayId(), + power_mode.cast()); } HWC::Error HardwareComposer::Present(hwc2_display_t display) { @@ -419,7 +425,7 @@ void HardwareComposer::PostLayers() { layer.Prepare(); } - HWC::Error error = Validate(HWC_DISPLAY_PRIMARY); + HWC::Error error = Validate(composer_callback_->GetDisplayId()); if (error != HWC::Error::None) { ALOGE("HardwareComposer::PostLayers: Validate failed: %s", error.to_string().c_str()); @@ -466,7 +472,7 @@ void HardwareComposer::PostLayers() { } #endif - error = Present(HWC_DISPLAY_PRIMARY); + error = Present(composer_callback_->GetDisplayId()); if (error != HWC::Error::None) { ALOGE("HardwareComposer::PostLayers: Present failed: %s", error.to_string().c_str()); @@ -475,8 +481,8 @@ void HardwareComposer::PostLayers() { std::vector out_layers; std::vector out_fences; - error = composer_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers, - &out_fences); + error = composer_->getReleaseFences(composer_callback_->GetDisplayId(), + &out_layers, &out_fences); ALOGE_IF(error != HWC::Error::None, "HardwareComposer::PostLayers: Failed to get release fences: %s", error.to_string().c_str()); @@ -615,14 +621,6 @@ int HardwareComposer::PostThreadPollInterruptible( } } -Status HardwareComposer::GetVSyncTime() { - auto status = composer_callback_->GetVsyncTime(HWC_DISPLAY_PRIMARY); - ALOGE_IF(!status, - "HardwareComposer::GetVSyncTime: Failed to get vsync timestamp: %s", - status.GetErrorMessage().c_str()); - return status; -} - // 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. @@ -795,8 +793,7 @@ void HardwareComposer::PostThread() { // Signal all of the vsync clients. Because absolute time is used for the // wakeup time below, this can take a little time if necessary. if (vsync_callback_) - vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp, - /*frame_time_estimate*/ 0, vsync_count_); + vsync_callback_(vsync_timestamp, /*frame_time_estimate*/ 0, vsync_count_); { // Sleep until shortly before vsync. @@ -819,7 +816,7 @@ void HardwareComposer::PostThread() { // If the layer config changed we need to validateDisplay() even if // we're going to drop the frame, to flush the Composer object's // internal command buffer and apply our layer changes. - Validate(HWC_DISPLAY_PRIMARY); + Validate(composer_callback_->GetDisplayId()); } continue; } @@ -827,7 +824,7 @@ void HardwareComposer::PostThread() { } { - auto status = GetVSyncTime(); + auto status = composer_callback_->GetVsyncTime(); if (!status) { ALOGE("HardwareComposer::PostThread: Failed to get VSYNC time: %s", status.GetErrorMessage().c_str()); @@ -946,10 +943,17 @@ void HardwareComposer::SetBacklightBrightness(int brightness) { } Return HardwareComposer::ComposerCallback::onHotplug( - Hwc2::Display display, IComposerCallback::Connection /*conn*/) { - // See if the driver supports the vsync_event node in sysfs. - if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES && - !displays_[display].driver_vsync_event_fd) { + Hwc2::Display display, IComposerCallback::Connection conn) { + // Our first onHotplug callback is always for the primary display. + // + // Ignore any other hotplug callbacks since the primary display is never + // disconnected and we don't care about other displays. + if (!has_display_id_) { + LOG_ALWAYS_FATAL_IF(conn != IComposerCallback::Connection::CONNECTED, + "Initial onHotplug callback should be primary display connected"); + has_display_id_ = true; + display_id_ = display; + std::array buffer; snprintf(buffer.data(), buffer.size(), "/sys/class/graphics/fb%" PRIu64 "/vsync_event", display); @@ -958,7 +962,7 @@ Return HardwareComposer::ComposerCallback::onHotplug( "HardwareComposer::ComposerCallback::onHotplug: Driver supports " "vsync_event node for display %" PRIu64, display); - displays_[display].driver_vsync_event_fd = std::move(handle); + driver_vsync_event_fd_ = std::move(handle); } else { ALOGI( "HardwareComposer::ComposerCallback::onHotplug: Driver does not " @@ -977,36 +981,23 @@ Return HardwareComposer::ComposerCallback::onRefresh( Return HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display, int64_t timestamp) { - TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|", - display, timestamp); - if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES) { - displays_[display].callback_vsync_timestamp = timestamp; - } else { - ALOGW( - "HardwareComposer::ComposerCallback::onVsync: Received vsync on " - "non-physical display: display=%" PRId64, - display); + // Ignore any onVsync callbacks for the non-primary display. + if (has_display_id_ && display == display_id_) { + TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|", + display, timestamp); + callback_vsync_timestamp_ = timestamp; } return Void(); } -Status HardwareComposer::ComposerCallback::GetVsyncTime( - Hwc2::Display display) { - if (display >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) { - ALOGE( - "HardwareComposer::ComposerCallback::GetVsyncTime: Invalid physical " - "display requested: display=%" PRIu64, - display); - return ErrorStatus(EINVAL); - } - +Status HardwareComposer::ComposerCallback::GetVsyncTime() { // See if the driver supports direct vsync events. - LocalHandle& event_fd = displays_[display].driver_vsync_event_fd; + LocalHandle& event_fd = driver_vsync_event_fd_; if (!event_fd) { // Fall back to returning the last timestamp returned by the vsync // callback. std::lock_guard autolock(vsync_mutex_); - return displays_[display].callback_vsync_timestamp; + return callback_vsync_timestamp_; } // When the driver supports the vsync_event sysfs node we can use it to @@ -1056,10 +1047,11 @@ Status HardwareComposer::ComposerCallback::GetVsyncTime( Hwc2::Composer* Layer::composer_{nullptr}; HWCDisplayMetrics Layer::display_metrics_{0, 0, {0, 0}, 0}; +hwc2_display_t Layer::display_id_{0}; void Layer::Reset() { if (hardware_composer_layer_) { - composer_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_); + composer_->destroyLayer(display_id_, hardware_composer_layer_); hardware_composer_layer_ = 0; } @@ -1154,17 +1146,16 @@ void Layer::UpdateVisibilitySettings() { pending_visibility_settings_ = false; HWC::Error error; - hwc2_display_t display = HWC_DISPLAY_PRIMARY; error = composer_->setLayerBlendMode( - display, hardware_composer_layer_, + display_id_, hardware_composer_layer_, blending_.cast()); ALOGE_IF(error != HWC::Error::None, "Layer::UpdateLayerSettings: Error setting layer blend mode: %s", error.to_string().c_str()); - error = - composer_->setLayerZOrder(display, hardware_composer_layer_, z_order_); + error = composer_->setLayerZOrder(display_id_, hardware_composer_layer_, + z_order_); ALOGE_IF(error != HWC::Error::None, "Layer::UpdateLayerSettings: Error setting z_ order: %s", error.to_string().c_str()); @@ -1173,36 +1164,35 @@ void Layer::UpdateVisibilitySettings() { void Layer::UpdateLayerSettings() { HWC::Error error; - hwc2_display_t display = HWC_DISPLAY_PRIMARY; UpdateVisibilitySettings(); // TODO(eieio): Use surface attributes or some other mechanism to control // the layer display frame. error = composer_->setLayerDisplayFrame( - display, hardware_composer_layer_, + display_id_, hardware_composer_layer_, {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 = composer_->setLayerVisibleRegion( - display, hardware_composer_layer_, + display_id_, hardware_composer_layer_, {{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 = - composer_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f); + error = composer_->setLayerPlaneAlpha(display_id_, hardware_composer_layer_, + 1.0f); ALOGE_IF(error != HWC::Error::None, "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s", error.to_string().c_str()); } void Layer::CommonLayerSetup() { - HWC::Error error = - composer_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_); + HWC::Error error = composer_->createLayer(display_id_, + &hardware_composer_layer_); ALOGE_IF(error != HWC::Error::None, "Layer::CommonLayerSetup: Failed to create layer on primary " "display: %s", @@ -1246,10 +1236,10 @@ void Layer::Prepare() { if (composition_type_ == HWC::Composition::Invalid) { composition_type_ = HWC::Composition::SolidColor; composer_->setLayerCompositionType( - HWC_DISPLAY_PRIMARY, hardware_composer_layer_, + display_id_, hardware_composer_layer_, composition_type_.cast()); Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0}; - composer_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_, + composer_->setLayerColor(display_id_, hardware_composer_layer_, layer_color); } else { // The composition type is already set. Nothing else to do until a @@ -1259,7 +1249,7 @@ void Layer::Prepare() { if (composition_type_ != target_composition_type_) { composition_type_ = target_composition_type_; composer_->setLayerCompositionType( - HWC_DISPLAY_PRIMARY, hardware_composer_layer_, + display_id_, hardware_composer_layer_, composition_type_.cast()); } @@ -1270,7 +1260,7 @@ void Layer::Prepare() { HWC::Error error{HWC::Error::None}; error = - composer_->setLayerBuffer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_, + composer_->setLayerBuffer(display_id_, hardware_composer_layer_, slot, handle, acquire_fence_.Get()); ALOGE_IF(error != HWC::Error::None, @@ -1280,7 +1270,7 @@ void Layer::Prepare() { if (!surface_rect_functions_applied_) { const float float_right = right; const float float_bottom = bottom; - error = composer_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY, + error = composer_->setLayerSourceCrop(display_id_, hardware_composer_layer_, {0, 0, float_right, float_bottom}); diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h index 7010db9630..9ed4b22a1d 100644 --- a/libs/vr/libvrflinger/hardware_composer.h +++ b/libs/vr/libvrflinger/hardware_composer.h @@ -152,6 +152,11 @@ class Layer { display_metrics_ = display_metrics; } + // Sets the display id used by all Layer instances. + static void SetDisplayId(hwc2_display_t display_id) { + display_id_ = display_id; + } + private: void CommonLayerSetup(); @@ -180,6 +185,11 @@ class Layer { // thereafter. static HWCDisplayMetrics display_metrics_; + // Id of the primary display. Shared by all instances of Layer. This must be + // set whenever the primary display id changes. This can be left unset as long + // as there are no instances of Layer that might need to use it. + static hwc2_display_t display_id_; + // The hardware composer layer and metrics to use during the prepare cycle. hwc2_layer_t hardware_composer_layer_ = 0; @@ -298,13 +308,14 @@ class Layer { class HardwareComposer { public: // Type for vsync callback. - using VSyncCallback = std::function; + using VSyncCallback = std::function; using RequestDisplayCallback = std::function; HardwareComposer(); ~HardwareComposer(); bool Initialize(Hwc2::Composer* composer, + hwc2_display_t primary_display_id, RequestDisplayCallback request_display_callback); bool IsInitialized() const { return initialized_; } @@ -362,16 +373,16 @@ class HardwareComposer { hardware::Return onVsync(Hwc2::Display display, int64_t timestamp) override; - pdx::Status GetVsyncTime(Hwc2::Display display); + bool HasDisplayId() { return has_display_id_; } + hwc2_display_t GetDisplayId() { return display_id_; } + pdx::Status GetVsyncTime(); private: std::mutex vsync_mutex_; - - struct Display { - pdx::LocalHandle driver_vsync_event_fd; - int64_t callback_vsync_timestamp{0}; - }; - std::array displays_; + bool has_display_id_ = false; + hwc2_display_t display_id_; + pdx::LocalHandle driver_vsync_event_fd_; + int64_t callback_vsync_timestamp_{0}; }; HWC::Error Validate(hwc2_display_t display); @@ -412,7 +423,6 @@ class HardwareComposer { // kPostThreadInterrupted. int ReadWaitPPState(); pdx::Status WaitForVSync(); - pdx::Status GetVSyncTime(); int SleepUntil(int64_t wakeup_timestamp); // Reconfigures the layer stack if the display surfaces changed since the last diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h index 33cbc84d7d..c740dde3d6 100644 --- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h +++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h @@ -4,6 +4,12 @@ #include #include +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + #include #include @@ -21,7 +27,9 @@ class VrFlinger { public: using RequestDisplayCallback = std::function; static std::unique_ptr Create( - Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback); + Hwc2::Composer* hidl, + hwc2_display_t primary_display_id, + RequestDisplayCallback request_display_callback); ~VrFlinger(); // These functions are all called on surface flinger's main thread. @@ -35,6 +43,7 @@ class VrFlinger { private: VrFlinger(); bool Init(Hwc2::Composer* hidl, + hwc2_display_t primary_display_id, RequestDisplayCallback request_display_callback); // Needs to be a separate class for binder's ref counting diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp index 85dc586eae..5e7abd7d96 100644 --- a/libs/vr/libvrflinger/vr_flinger.cpp +++ b/libs/vr/libvrflinger/vr_flinger.cpp @@ -29,9 +29,10 @@ namespace android { namespace dvr { std::unique_ptr VrFlinger::Create( - Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) { + Hwc2::Composer* hidl, hwc2_display_t primary_display_id, + RequestDisplayCallback request_display_callback) { std::unique_ptr vr_flinger(new VrFlinger); - if (vr_flinger->Init(hidl, request_display_callback)) + if (vr_flinger->Init(hidl, primary_display_id, request_display_callback)) return vr_flinger; else return nullptr; @@ -56,6 +57,7 @@ VrFlinger::~VrFlinger() { } bool VrFlinger::Init(Hwc2::Composer* hidl, + hwc2_display_t primary_display_id, RequestDisplayCallback request_display_callback) { if (!hidl || !request_display_callback) return false; @@ -74,8 +76,8 @@ bool VrFlinger::Init(Hwc2::Composer* hidl, dispatcher_ = android::pdx::ServiceDispatcher::Create(); CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher."); - display_service_ = - android::dvr::DisplayService::Create(hidl, request_display_callback); + display_service_ = android::dvr::DisplayService::Create( + hidl, primary_display_id, request_display_callback); CHECK_ERROR(!display_service_, error, "Failed to create display service."); dispatcher_->AddService(display_service_); @@ -91,7 +93,7 @@ bool VrFlinger::Init(Hwc2::Composer* hidl, std::bind(&android::dvr::VSyncService::VSyncEvent, std::static_pointer_cast(service), std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4)); + std::placeholders::_3)); dispatcher_thread_ = std::thread([this]() { prctl(PR_SET_NAME, reinterpret_cast("VrDispatch"), 0, 0, 0); diff --git a/libs/vr/libvrflinger/vsync_service.cpp b/libs/vr/libvrflinger/vsync_service.cpp index fdeb899f66..b8d8b08b5f 100644 --- a/libs/vr/libvrflinger/vsync_service.cpp +++ b/libs/vr/libvrflinger/vsync_service.cpp @@ -32,21 +32,19 @@ VSyncService::VSyncService() VSyncService::~VSyncService() {} -void VSyncService::VSyncEvent(int display, int64_t timestamp_ns, +void VSyncService::VSyncEvent(int64_t timestamp_ns, int64_t compositor_time_ns, uint32_t vsync_count) { ATRACE_NAME("VSyncService::VSyncEvent"); std::lock_guard autolock(mutex_); - if (display == HWC_DISPLAY_PRIMARY) { - last_vsync_ = current_vsync_; - current_vsync_ = timestamp_ns; - compositor_time_ns_ = compositor_time_ns; - current_vsync_count_ = vsync_count; + last_vsync_ = current_vsync_; + current_vsync_ = timestamp_ns; + compositor_time_ns_ = compositor_time_ns; + current_vsync_count_ = vsync_count; - NotifyWaiters(); - UpdateClients(); - } + NotifyWaiters(); + UpdateClients(); } std::shared_ptr VSyncService::OnChannelOpen(pdx::Message& message) { diff --git a/libs/vr/libvrflinger/vsync_service.h b/libs/vr/libvrflinger/vsync_service.h index 215948eb05..822f02b266 100644 --- a/libs/vr/libvrflinger/vsync_service.h +++ b/libs/vr/libvrflinger/vsync_service.h @@ -63,9 +63,10 @@ class VSyncService : public pdx::ServiceBase { const std::shared_ptr& channel) override; // Called by the hardware composer HAL, or similar, whenever a vsync event - // occurs. |compositor_time_ns| is the number of ns before the next vsync when - // the compositor will preempt the GPU to do EDS and lens warp. - void VSyncEvent(int display, int64_t timestamp_ns, int64_t compositor_time_ns, + // occurs on the primary display. |compositor_time_ns| is the number of ns + // before the next vsync when the compositor will preempt the GPU to do EDS + // and lens warp. + void VSyncEvent(int64_t timestamp_ns, int64_t compositor_time_ns, uint32_t vsync_count); private: diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 2a78aa597f..ecee8ce097 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -150,7 +150,7 @@ ifdef TARGET_32_BIT_SURFACEFLINGER LOCAL_32_BIT_ONLY := true endif -LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code +LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -std=c++1z include $(BUILD_EXECUTABLE) diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 5328a228bc..60b85c5b4d 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -868,6 +868,14 @@ void HWComposer::dump(String8& result) const { result.append(mHwcDevice->dump().c_str()); } +std::optional +HWComposer::getHwcDisplayId(int32_t displayId) const { + if (!isValidDisplay(displayId)) { + return {}; + } + return mDisplayData[displayId].hwcDisplay->getId(); +} + // --------------------------------------------------------------------------- HWComposer::DisplayData::DisplayData() diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 3b6d931b5c..74b3a38b6a 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -161,6 +162,8 @@ public: void dump(String8& out) const; android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); } + + std::optional getHwcDisplayId(int32_t displayId) const; private: static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4c03112984..771d20706a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -649,7 +649,8 @@ void SurfaceFlinger::init() { postMessageAsync(message); }; mVrFlinger = dvr::VrFlinger::Create(mHwc->getComposer(), - vrFlingerRequestDisplayCallback); + mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0), + vrFlingerRequestDisplayCallback); if (!mVrFlinger) { ALOGE("Failed to start vrflinger"); } diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 212b9e7ebb..47c4f4abb7 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -31,6 +31,9 @@ cc_test { "libtrace_proto", "libgmock" ], + cppflags: [ + "-std=c++1z", + ], tags: ["tests"], test_suites: ["device-tests"] } \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 7206d49b2963ce2e926a5f25fe94aca9c06471e6 Mon Sep 17 00:00:00 2001 From: chaviw Date: Fri, 10 Nov 2017 16:16:12 -0800 Subject: Add additional parameters for the captureLayer functions. 1. Added new captureLayers function that will return a GraphicBuffer instead of storing into a Surface. 2. Added crop to captureLayers function. 3. Added frameScale to allow captures to scale. 4. Removed rotation parameter from captureLayers since it will always be in the correct orientation. Test: Transaction_test ScreenCaptureTest.CaptureCrop, .CaptureSize Change-Id: Ib16d8575cf0c103126b9427ad32e2d28d568ea61 --- libs/gui/ISurfaceComposer.cpp | 12 +-- libs/gui/SurfaceComposerClient.cpp | 29 ++++++- libs/gui/include/gui/ISurfaceComposer.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 6 +- libs/gui/tests/Surface_test.cpp | 2 +- services/surfaceflinger/RenderArea.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 42 ++++++++-- services/surfaceflinger/SurfaceFlinger.h | 2 +- services/surfaceflinger/tests/Transaction_test.cpp | 93 +++++++++++++++++++++- 9 files changed, 166 insertions(+), 25 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 973302c226..c21c5e3eb8 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -124,12 +124,13 @@ public: virtual status_t captureLayers(const sp& layerHandleBinder, const sp& producer, - ISurfaceComposer::Rotation rotation) { + const Rect& sourceCrop, float frameScale) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); data.writeStrongBinder(IInterface::asBinder(producer)); - data.writeInt32(static_cast(rotation)); + data.write(sourceCrop); + data.writeFloat(frameScale); remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); return reply.readInt32(); } @@ -605,10 +606,11 @@ status_t BnSurfaceComposer::onTransact( sp layerHandleBinder = data.readStrongBinder(); sp producer = interface_cast(data.readStrongBinder()); - int32_t rotation = data.readInt32(); + Rect sourceCrop(Rect::EMPTY_RECT); + data.read(sourceCrop); + float frameScale = data.readFloat(); - status_t res = captureLayers(layerHandleBinder, producer, - static_cast(rotation)); + status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale); reply->writeInt32(res); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2adc273651..2466d2555a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -757,11 +757,34 @@ status_t ScreenshotClient::captureToBuffer(const sp& display, status_t ScreenshotClient::captureLayers(const sp& layerHandle, const sp& producer, - uint32_t rotation) { + Rect sourceCrop, float frameScale) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureLayers(layerHandle, producer, - static_cast(rotation)); + return s->captureLayers(layerHandle, producer, sourceCrop, frameScale); +} + +status_t ScreenshotClient::captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + + sp gbpConsumer; + sp producer; + BufferQueue::createBufferQueue(&producer, &gbpConsumer); + sp consumer(new BufferItemConsumer(gbpConsumer, + GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_SW_READ_NEVER | + GRALLOC_USAGE_SW_WRITE_NEVER, + 1, true)); + + status_t ret = s->captureLayers(layerHandle, producer, sourceCrop, frameScale); + if (ret != NO_ERROR) { + return ret; + } + BufferItem b; + consumer->acquireBuffer(&b, 0, true); + *outBuffer = b.mGraphicBuffer; + return ret; } ScreenshotClient::ScreenshotClient() diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 13e7473d54..1e4c329e1e 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -176,7 +176,7 @@ public: virtual status_t captureLayers(const sp& layerHandleBinder, const sp& producer, - Rotation rotation = eRotateNone) = 0; + const Rect& sourceCrop, float frameScale = 1.0) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 87fdfae111..b0fa922cd9 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -297,8 +297,12 @@ public: bool useIdentityTransform, uint32_t rotation, sp* outbuffer); + static status_t captureLayers(const sp& layerHandle, - const sp& producer, uint32_t rotation); + const sp& producer, Rect sourceCrop, + float frameScale); + static status_t captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer); private: mutable sp mCpuConsumer; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 660680bf9e..ac4eb0cb1d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -531,7 +531,7 @@ public: Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, const sp& /*producer*/, - ISurfaceComposer::Rotation /*rotation*/) override { + const Rect& /*sourceCrop*/, float /*frameScale*/) override { return NO_ERROR; } status_t clearAnimationFrameStats() override { return NO_ERROR; } diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 44b9dc9254..fa4df8360f 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -6,7 +6,8 @@ namespace android { class RenderArea { public: - RenderArea(uint32_t reqHeight, uint32_t reqWidth, ISurfaceComposer::Rotation rotation) + RenderArea(uint32_t reqHeight, uint32_t reqWidth, + ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone) : mReqHeight(reqHeight), mReqWidth(reqWidth) { mRotationFlags = Transform::fromRotation(rotation); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ec2a459fb2..ea4f495d59 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4398,15 +4398,14 @@ status_t SurfaceFlinger::captureScreen(const sp& display, status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, const sp& producer, - ISurfaceComposer::Rotation rotation) { + const Rect& sourceCrop, float frameScale) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: - LayerRenderArea(const sp& layer, ISurfaceComposer::Rotation rotation) - : RenderArea(layer->getCurrentState().active.h, layer->getCurrentState().active.w, - rotation), - mLayer(layer) {} + LayerRenderArea(const sp& layer, const Rect crop, int32_t reqWidth, + int32_t reqHeight) + : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} const Transform& getTransform() const override { // Make the top level transform the inverse the transform and it's parent so it sets // the whole capture back to 0,0 @@ -4421,18 +4420,45 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } - Rect getSourceCrop() const override { return getBounds(); } + Rect getSourceCrop() const override { + if (mCrop.isEmpty()) { + return getBounds(); + } else { + return mCrop; + } + } bool getWideColorSupport() const override { return false; } android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; } private: - const sp& mLayer; + const sp mLayer; + const Rect mCrop; }; auto layerHandle = reinterpret_cast(layerHandleBinder.get()); auto parent = layerHandle->owner.promote(); - LayerRenderArea renderArea(parent, rotation); + if (parent == nullptr || parent->isPendingRemoval()) { + ALOGE("captureLayers called with a removed parent"); + return NAME_NOT_FOUND; + } + + Rect crop(sourceCrop); + if (sourceCrop.width() <= 0) { + crop.left = 0; + crop.right = parent->getCurrentState().active.w; + } + + if (sourceCrop.height() <= 0) { + crop.top = 0; + crop.bottom = parent->getCurrentState().active.h; + } + + int32_t reqWidth = crop.width() * frameScale; + int32_t reqHeight = crop.height() * frameScale; + + LayerRenderArea renderArea(parent, crop, reqWidth, reqHeight); + auto traverseLayers = [parent](const LayerVector::Visitor& visitor) { parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { if (!layer->isVisible()) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 386d42bef1..f61dc756c2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -298,7 +298,7 @@ private: bool useIdentityTransform, ISurfaceComposer::Rotation rotation); virtual status_t captureLayers(const sp& parentHandle, const sp& producer, - ISurfaceComposer::Rotation rotation); + const Rect& sourceCrop, float frameScale); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp& display, diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 943fafd213..39aef8164c 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -276,15 +276,15 @@ private: class CaptureLayer { public: - static void captureScreen(std::unique_ptr* sc, sp& parentHandle) { + static void captureScreen(std::unique_ptr* sc, sp& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { sp producer; sp consumer; BufferQueue::createBufferQueue(&producer, &consumer); sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); - sp display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); SurfaceComposerClient::Transaction().apply(true); - ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer)); + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale)); *sc = std::make_unique(cpuConsumer); } @@ -2412,4 +2412,89 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { mCapture->checkPixel(4, 4, 50, 50, 50); } -} // namespace android +TEST_F(ScreenCaptureTest, CaptureCrop) { + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = mComposerClient->createSurface( + String8("Blue surface"), + 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + + fillSurfaceRGBA8(redLayer, 255, 0, 0); + fillSurfaceRGBA8(blueLayer, 0, 0, 255); + + SurfaceComposerClient::Transaction() + .setLayer(redLayer, INT32_MAX-1) + .show(redLayer) + .show(blueLayer) + .apply(true); + + auto redLayerHandle = redLayer->getHandle(); + + // Capturing full screen should have both red and blue are visible. + CaptureLayer::captureScreen(&mCapture, redLayerHandle); + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 255, 0, 0); + + Rect crop = Rect(0, 0, 30, 30); + CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop); + // Capturing the cropped screen, cropping out the shown red area, should leave only the blue + // area visible. + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 0, 0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureSize) { + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = mComposerClient->createSurface( + String8("Blue surface"), + 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + + fillSurfaceRGBA8(redLayer, 255, 0, 0); + fillSurfaceRGBA8(blueLayer, 0, 0, 255); + + SurfaceComposerClient::Transaction() + .setLayer(redLayer, INT32_MAX-1) + .show(redLayer) + .show(blueLayer) + .apply(true); + + auto redLayerHandle = redLayer->getHandle(); + + // Capturing full screen should have both red and blue are visible. + CaptureLayer::captureScreen(&mCapture, redLayerHandle); + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 255, 0, 0); + + CaptureLayer::captureScreen(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); + // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. + mCapture->checkPixel(14, 14, 0, 0, 255); + mCapture->checkPixel(15, 15, 255, 0, 0); + mCapture->checkPixel(29, 29, 255, 0, 0); + mCapture->checkPixel(30, 30, 0, 0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + + fillSurfaceRGBA8(redLayer, 255, 0, 0); + + auto redLayerHandle = redLayer->getHandle(); + mComposerClient->destroySurface(redLayerHandle); + SurfaceComposerClient::Transaction().apply(true); + + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); + sp sf(ComposerService::getComposerService()); + + // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND + ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0)); +} + +} \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From ebd62af1a1efcd200c7f7ecf5f165a31568907b0 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 28 Nov 2017 08:49:59 -0800 Subject: SurfaceFlinger: Fix removal check when adding child layers. Traversing the current state has the same problem we had in other CL's with relative Z. In this case if there was a parent that was relative-Zed then it's Z relative is removed, we will be unable to add children to it until we assign it a new layer. However there's no reason to traverse, we can just use the new "isPendingRemoval" flag to detect this state. Bug: 69633137 Test: Existing tests pass. Change-Id: I4584f051346fe77c3e6158a04dd1279a86164476 --- services/surfaceflinger/SurfaceFlinger.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ec2a459fb2..0351b9f553 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2869,14 +2869,7 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, if (parent == nullptr) { mCurrentState.layersSortedByZ.add(lbc); } else { - bool found = false; - mCurrentState.traverseInZOrder([&](Layer* layer) { - if (layer == parent.get()) { - found = true; - } - }); - - if (!found) { + if (parent->isPendingRemoval()) { ALOGE("addClientLayer called with a removed parent"); return NAME_NOT_FOUND; } -- cgit v1.2.3-59-g8ed1b From a252d895816b3aa6c3bc2b2083113694ead6963d Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 20 Nov 2017 17:54:25 -0800 Subject: Use GraphicBuffer instead of GBP for screenshots. Migrate screenshot code to render the layers into a GraphicBuffer instead of creating a GraphicBufferProducer. This cleans up the code and makes rendering a screen capture simpler and clearer. Test: Screencaptures for Recents, manual screenshots, and "adb shell screencap" Test: Transaction_test Change-Id: Ifb463c0e98cfaa3f96ad27837b1a2e2921e253d1 --- libs/gui/ISurfaceComposer.cpp | 71 ++++--- libs/gui/Surface.cpp | 21 ++ libs/gui/SurfaceComposerClient.cpp | 174 +--------------- libs/gui/include/gui/ISurfaceComposer.h | 15 +- libs/gui/include/gui/Surface.h | 2 + libs/gui/include/gui/SurfaceComposerClient.h | 72 +------ libs/gui/tests/Surface_test.cpp | 13 +- services/surfaceflinger/SurfaceFlinger.cpp | 112 +++------- services/surfaceflinger/SurfaceFlinger.h | 18 +- services/surfaceflinger/tests/Transaction_test.cpp | 229 +++++++++------------ 10 files changed, 227 insertions(+), 500 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index c21c5e3eb8..5de84ecbab 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -100,17 +100,13 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - ISurfaceComposer::Rotation rotation) - { + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); @@ -118,21 +114,45 @@ public: data.writeInt32(maxLayerZ); data.writeInt32(static_cast(useIdentityTransform)); data.writeInt32(static_cast(rotation)); - remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); - return reply.readInt32(); + status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); + + if (err != NO_ERROR) { + return err; + } + + err = reply.readInt32(); + if (err != NO_ERROR) { + return err; + } + + *outBuffer = new GraphicBuffer(); + reply.read(**outBuffer); + return err; } virtual status_t captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale) { + sp* outBuffer, const Rect& sourceCrop, + float frameScale) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); - data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeFloat(frameScale); - remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); - return reply.readInt32(); + status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); + + if (err != NO_ERROR) { + return err; + } + + err = reply.readInt32(); + if (err != NO_ERROR) { + return err; + } + + *outBuffer = new GraphicBuffer(); + reply.read(**outBuffer); + + return err; } virtual bool authenticateSurfaceTexture( @@ -583,8 +603,7 @@ status_t BnSurfaceComposer::onTransact( case CAPTURE_SCREEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); - sp producer = - interface_cast(data.readStrongBinder()); + sp outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); uint32_t reqWidth = data.readUint32(); @@ -594,24 +613,28 @@ status_t BnSurfaceComposer::onTransact( bool useIdentityTransform = static_cast(data.readInt32()); int32_t rotation = data.readInt32(); - status_t res = captureScreen(display, producer, - sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, - static_cast(rotation)); + status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight, + minLayerZ, maxLayerZ, useIdentityTransform, + static_cast(rotation)); reply->writeInt32(res); + if (res == NO_ERROR) { + reply->write(*outBuffer); + } return NO_ERROR; } case CAPTURE_LAYERS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp layerHandleBinder = data.readStrongBinder(); - sp producer = - interface_cast(data.readStrongBinder()); + sp outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); float frameScale = data.readFloat(); - status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale); + status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale); reply->writeInt32(res); + if (res == NO_ERROR) { + reply->write(*outBuffer); + } return NO_ERROR; } case AUTHENTICATE_SURFACE: { diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e9393831c7..80216bc63e 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1760,4 +1760,25 @@ status_t Surface::getAndFlushRemovedBuffers(std::vector>* out) return OK; } +status_t Surface::attachAndQueueBuffer(Surface* surface, sp buffer) { + if (buffer == nullptr) { + return BAD_VALUE; + } + int err = static_cast(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT, + NATIVE_WINDOW_API_CPU); + if (err != OK) { + return err; + } + err = surface->attachBuffer(buffer->getNativeBuffer()); + if (err != OK) { + return err; + } + err = static_cast(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1); + if (err != OK) { + return err; + } + err = surface->disconnect(NATIVE_WINDOW_API_CPU); + return err; +} + }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2466d2555a..0dbe786f1a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -717,181 +717,27 @@ status_t SurfaceComposerClient::getHdrCapabilities(const sp& display, // ---------------------------------------------------------------------------- -status_t ScreenshotClient::capture( - const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) { +status_t ScreenshotClient::capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation, + sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureScreen(display, producer, sourceCrop, - reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform); -} - -status_t ScreenshotClient::captureToBuffer(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - uint32_t rotation, - sp* outBuffer) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - - sp gbpConsumer; - sp producer; - BufferQueue::createBufferQueue(&producer, &gbpConsumer); - sp consumer(new BufferItemConsumer(gbpConsumer, - GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER, - 1, true)); - - status_t ret = s->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, - static_cast(rotation)); + status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ, + maxLayerZ, useIdentityTransform, + static_cast(rotation)); if (ret != NO_ERROR) { return ret; } - BufferItem b; - consumer->acquireBuffer(&b, 0, true); - *outBuffer = b.mGraphicBuffer; return ret; } -status_t ScreenshotClient::captureLayers(const sp& layerHandle, - const sp& producer, - Rect sourceCrop, float frameScale) { +status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureLayers(layerHandle, producer, sourceCrop, frameScale); -} - -status_t ScreenshotClient::captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, - float frameScale, sp* outBuffer) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - - sp gbpConsumer; - sp producer; - BufferQueue::createBufferQueue(&producer, &gbpConsumer); - sp consumer(new BufferItemConsumer(gbpConsumer, - GRALLOC_USAGE_HW_TEXTURE | - GRALLOC_USAGE_SW_READ_NEVER | - GRALLOC_USAGE_SW_WRITE_NEVER, - 1, true)); - - status_t ret = s->captureLayers(layerHandle, producer, sourceCrop, frameScale); - if (ret != NO_ERROR) { - return ret; - } - BufferItem b; - consumer->acquireBuffer(&b, 0, true); - *outBuffer = b.mGraphicBuffer; + status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale); return ret; } - -ScreenshotClient::ScreenshotClient() - : mHaveBuffer(false) { - memset(&mBuffer, 0, sizeof(mBuffer)); -} - -ScreenshotClient::~ScreenshotClient() { - ScreenshotClient::release(); -} - -sp ScreenshotClient::getCpuConsumer() const { - if (mCpuConsumer == NULL) { - sp consumer; - BufferQueue::createBufferQueue(&mProducer, &consumer); - mCpuConsumer = new CpuConsumer(consumer, 1); - mCpuConsumer->setName(String8("ScreenshotClient")); - } - return mCpuConsumer; -} - -status_t ScreenshotClient::update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - sp cpuConsumer = getCpuConsumer(); - - if (mHaveBuffer) { - mCpuConsumer->unlockBuffer(mBuffer); - memset(&mBuffer, 0, sizeof(mBuffer)); - mHaveBuffer = false; - } - - status_t err = s->captureScreen(display, mProducer, sourceCrop, - reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, - static_cast(rotation)); - - if (err == NO_ERROR) { - err = mCpuConsumer->lockNextBuffer(&mBuffer); - if (err == NO_ERROR) { - mHaveBuffer = true; - } - } - return err; -} - -status_t ScreenshotClient::update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform) { - - return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, - bool useIdentityTransform) { - return ScreenshotClient::update(display, sourceCrop, 0, 0, - INT32_MIN, INT32_MAX, - useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) { - return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, - INT32_MIN, INT32_MAX, - useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -void ScreenshotClient::release() { - if (mHaveBuffer) { - mCpuConsumer->unlockBuffer(mBuffer); - memset(&mBuffer, 0, sizeof(mBuffer)); - mHaveBuffer = false; - } - mCpuConsumer.clear(); -} - -void const* ScreenshotClient::getPixels() const { - return mBuffer.data; -} - -uint32_t ScreenshotClient::getWidth() const { - return mBuffer.width; -} - -uint32_t ScreenshotClient::getHeight() const { - return mBuffer.height; -} - -PixelFormat ScreenshotClient::getFormat() const { - return mBuffer.format; -} - -uint32_t ScreenshotClient::getStride() const { - return mBuffer.stride; -} - -size_t ScreenshotClient::getSize() const { - return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format); -} - -android_dataspace ScreenshotClient::getDataSpace() const { - return mBuffer.dataSpace; -} - // ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 1e4c329e1e..e26e332589 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -29,6 +29,7 @@ #include #include +#include #include @@ -167,16 +168,14 @@ public: /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. */ - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - Rotation rotation = eRotateNone) = 0; + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + Rotation rotation = eRotateNone) = 0; virtual status_t captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale = 1.0) = 0; + sp* outBuffer, const Rect& sourceCrop, + float frameScale = 1.0) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 3fe29d955b..354f23ab06 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -283,6 +283,8 @@ public: android_dataspace_t getBuffersDataSpace(); + static status_t attachAndQueueBuffer(Surface* surface, sp buffer); + protected: enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index b0fa922cd9..3f13946339 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -279,74 +279,16 @@ private: // --------------------------------------------------------------------------- -class ScreenshotClient -{ +class ScreenshotClient { public: // if cropping isn't required, callers may pass in a default Rect, e.g.: // capture(display, producer, Rect(), reqWidth, ...); - static status_t capture( - const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform); - static status_t captureToBuffer( - const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - uint32_t rotation, - sp* outbuffer); - - static status_t captureLayers(const sp& layerHandle, - const sp& producer, Rect sourceCrop, - float frameScale); - static status_t captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, - float frameScale, sp* outBuffer); - -private: - mutable sp mCpuConsumer; - mutable sp mProducer; - CpuConsumer::LockedBuffer mBuffer; - bool mHaveBuffer; - -public: - ScreenshotClient(); - ~ScreenshotClient(); - - // frees the previous screenshot and captures a new one - // if cropping isn't required, callers may pass in a default Rect, e.g.: - // update(display, Rect(), useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation); - - sp getCpuConsumer() const; - - // release memory occupied by the screenshot - void release(); - - // pixels are valid until this object is freed or - // release() or update() is called - void const* getPixels() const; - - uint32_t getWidth() const; - uint32_t getHeight() const; - PixelFormat getFormat() const; - uint32_t getStride() const; - // size of allocated memory in bytes - size_t getSize() const; - android_dataspace getDataSpace() const; + static status_t capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation, + sp* outBuffer); + static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float fameScale, + sp* outBuffer); }; // --------------------------------------------------------------------------- diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index ac4eb0cb1d..470a338639 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -116,14 +116,11 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { sp anw(mSurface); // Verify the screenshot works with no protected buffers. - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay( ISurfaceComposer::eDisplayIdMain)); - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), + sp outBuffer; + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), 64, 64, 0, 0x7fffffff, false)); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), @@ -154,7 +151,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { &buf)); ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), 64, 64, 0, 0x7fffffff, false)); } @@ -524,13 +521,13 @@ public: status_t setActiveColorMode(const sp& /*display*/, android_color_mode_t /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp& /*display*/, - const sp& /*producer*/, + sp* /*outBuffer*/, Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/, bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, - const sp& /*producer*/, + sp* /*outBuffer*/, const Rect& /*sourceCrop*/, float /*frameScale*/) override { return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d81178c559..4acd448293 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4339,44 +4339,10 @@ private: const int mApi; }; -static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth, - uint32_t requestedHeight, bool hasWideColorDisplay, - bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) { - const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - - int err = 0; - err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight); - err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); - err |= native_window_set_usage(window, usage); - - if (hasWideColorDisplay) { - err |= native_window_set_buffers_data_space(window, - renderEngineUsesWideColor - ? HAL_DATASPACE_DISPLAY_P3 - : HAL_DATASPACE_V0_SRGB); - } - - if (err != NO_ERROR) { - return BAD_VALUE; - } - - /* TODO: Once we have the sync framework everywhere this can use - * server-side waits on the fence that dequeueBuffer returns. - */ - err = native_window_dequeue_buffer_and_wait(window, outBuffer); - if (err != NO_ERROR) { - return err; - } - - return NO_ERROR; -} - -status_t SurfaceFlinger::captureScreen(const sp& display, - const sp& producer, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, - int32_t maxLayerZ, bool useIdentityTransform, +status_t SurfaceFlinger::captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); @@ -4387,18 +4353,18 @@ status_t SurfaceFlinger::captureScreen(const sp& display, auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, device, minLayerZ, maxLayerZ, std::placeholders::_1); - return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform); + return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform); } status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale) { + sp* outBuffer, const Rect& sourceCrop, + float frameScale) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: LayerRenderArea(const sp& layer, const Rect crop, int32_t reqWidth, - int32_t reqHeight) + int32_t reqHeight) : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} const Transform& getTransform() const override { // Make the top level transform the inverse the transform and it's parent so it sets @@ -4461,51 +4427,21 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, visitor(layer); }); }; - return captureScreenCommon(renderArea, traverseLayers, producer, false); + return captureScreenCommon(renderArea, traverseLayers, outBuffer, false); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const sp& producer, + sp* outBuffer, bool useIdentityTransform) { ATRACE_CALL(); - if (CC_UNLIKELY(producer == 0)) - return BAD_VALUE; - renderArea.updateDimensions(); - // if we have secure windows on this display, never allow the screen capture - // unless the producer interface is local (i.e.: we can take a screenshot for - // ourselves). - bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder(); - - // create a surface (because we're a producer, and we need to - // dequeue/queue a buffer) - sp surface = new Surface(producer, false); - - // Put the screenshot Surface into async mode so that - // Layer::headFenceHasSignaled will always return true and we'll latch the - // first buffer regardless of whether or not its acquire fence has - // signaled. This is needed to avoid a race condition in the rotation - // animation. See b/30209608 - surface->setAsyncMode(true); - - ANativeWindow* window = surface.get(); - - status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); - if (result != NO_ERROR) { - return result; - } - WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL); - - ANativeWindowBuffer* buffer = nullptr; - result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(), - hasWideColorDisplay && !mForceNativeColorMode, - getRenderEngine().usesWideColor(), &buffer); - if (result != NO_ERROR) { - return result; - } + const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; + *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(), + HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot"); // This mutex protects syncFd and captureResult for communication of the return values from the // main thread back to this Binder thread @@ -4530,8 +4466,8 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, int fd = -1; { Mutex::Autolock _l(mStateLock); - result = captureScreenImplLocked(renderArea, traverseLayers, buffer, - useIdentityTransform, isLocalScreenshot, &fd); + result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), + useIdentityTransform, &fd); } { @@ -4542,7 +4478,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } }); - result = postMessageAsync(message); + status_t result = postMessageAsync(message); if (result == NO_ERROR) { captureCondition.wait(captureLock, [&]() { return captureResult; }); while (*captureResult == EAGAIN) { @@ -4557,9 +4493,10 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } if (result == NO_ERROR) { - // queueBuffer takes ownership of syncFd - result = window->queueBuffer(window, buffer, syncFd); + sync_wait(syncFd, -1); + close(syncFd); } + return result; } @@ -4602,7 +4539,8 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, } engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode); - engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode()); + engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE + : renderArea.getActiveColorMode()); // make sure to clear all GL error flags engine.checkErrors(); @@ -4645,7 +4583,7 @@ private: status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, - bool useIdentityTransform, bool isLocalScreenshot, + bool useIdentityTransform, int* outSyncFd) { ATRACE_CALL(); @@ -4655,7 +4593,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure()); }); - if (!isLocalScreenshot && secureLayerIsVisible) { + if (secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); return PERMISSION_DENIED; } @@ -4804,4 +4742,4 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" -#endif +#endif \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f61dc756c2..a01d353a70 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -291,13 +291,11 @@ private: std::vector* outSupported) const; virtual sp createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp); - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation); - virtual status_t captureLayers(const sp& parentHandle, - const sp& producer, + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation); + virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, const Rect& sourceCrop, float frameScale); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); @@ -436,15 +434,13 @@ private: void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, bool yswap, bool useIdentityTransform); - status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const sp& producer, + sp* outBuffer, bool useIdentityTransform); - status_t captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, - bool isLocalScreenshot, int* outSyncFd); + int* outSyncFd); void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 39aef8164c..ff81dc9461 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -104,20 +104,22 @@ void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const } // Check if a region has the specified color. -void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect, +void expectBufferColor(const sp& outBuffer, uint8_t* pixels, const Rect& rect, const Color& color, uint8_t tolerance) { int32_t x = rect.left; int32_t y = rect.top; int32_t width = rect.right - rect.left; int32_t height = rect.bottom - rect.top; - if (x + width > int32_t(buffer.width)) { - x = std::min(x, int32_t(buffer.width)); - width = buffer.width - x; + int32_t bufferWidth = int32_t(outBuffer->getWidth()); + int32_t bufferHeight = int32_t(outBuffer->getHeight()); + if (x + width > bufferWidth) { + x = std::min(x, bufferWidth); + width = bufferWidth - x; } - if (y + height > int32_t(buffer.height)) { - y = std::min(y, int32_t(buffer.height)); - height = buffer.height - y; + if (y + height > bufferHeight) { + y = std::min(y, bufferHeight); + height = bufferHeight - y; } auto colorCompare = [tolerance](uint8_t a, uint8_t b) { @@ -125,8 +127,7 @@ void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect return tmp <= tolerance; }; for (int32_t j = 0; j < height; j++) { - const uint8_t* src = - static_cast(buffer.data) + (buffer.stride * (y + j) + x) * 4; + const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) @@ -170,30 +171,38 @@ class ScreenCapture : public RefBase { public: static void captureScreen(sp* sc, int32_t minLayerZ = 0, int32_t maxLayerZ = std::numeric_limits::max()) { - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); SurfaceComposerClient::Transaction().apply(true); + sp outBuffer; ASSERT_EQ(NO_ERROR, - sf->captureScreen(display, producer, Rect(), 0, 0, minLayerZ, maxLayerZ, false)); - *sc = new ScreenCapture(cpuConsumer); + sf->captureScreen(display, &outBuffer, Rect(), 0, 0, minLayerZ, maxLayerZ, + false)); + *sc = new ScreenCapture(outBuffer); + } + + static void captureLayers(std::unique_ptr* sc, sp& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { + sp sf(ComposerService::getComposerService()); + SurfaceComposerClient::Transaction().apply(true); + + sp outBuffer; + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale)); + *sc = std::make_unique(outBuffer); } void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); - expectBufferColor(mBuf, rect, color, tolerance); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); + expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance); } void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); const bool leftBorder = rect.left > 0; const bool topBorder = rect.top > 0; - const bool rightBorder = rect.right < int32_t(mBuf.width); - const bool bottomBorder = rect.bottom < int32_t(mBuf.height); + const bool rightBorder = rect.right < int32_t(mOutBuffer->getWidth()); + const bool bottomBorder = rect.bottom < int32_t(mOutBuffer->getHeight()); if (topBorder) { Rect top(rect.left, rect.top - 1, rect.right, rect.top); @@ -246,9 +255,8 @@ public: } void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); - const uint8_t* img = static_cast(mBuf.data); - const uint8_t* pixel = img + (4 * (y * mBuf.stride + x)); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); + const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x)); if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { String8 err(String8::format("pixel @ (%3d, %3d): " "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", @@ -263,58 +271,15 @@ public: void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } -private: - ScreenCapture(const sp& cc) : mCC(cc) { - EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf)); + ScreenCapture(const sp& outBuffer) : mOutBuffer(outBuffer) { + mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast(&mPixels)); } - ~ScreenCapture() { mCC->unlockBuffer(mBuf); } - - sp mCC; - CpuConsumer::LockedBuffer mBuf; -}; - -class CaptureLayer { -public: - static void captureScreen(std::unique_ptr* sc, sp& parentHandle, - Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - sp sf(ComposerService::getComposerService()); - SurfaceComposerClient::Transaction().apply(true); - ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale)); - *sc = std::make_unique(cpuConsumer); - } - - void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuffer.format); - const uint8_t* img = static_cast(mBuffer.data); - const uint8_t* pixel = img + (4 * (y * mBuffer.stride + x)); - if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { - String8 err(String8::format("pixel @ (%3d, %3d): " - "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", - x, y, r, g, b, pixel[0], pixel[1], pixel[2])); - EXPECT_EQ(String8(), err) << err.string(); - } - } - - void expectFGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 195, 63, 63); } - - void expectBGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 63, 63, 195); } - - void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } - - CaptureLayer(const sp& cc) : mCC(cc) { - EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuffer)); - } - - ~CaptureLayer() { mCC->unlockBuffer(mBuffer); } + ~ScreenCapture() { mOutBuffer->unlock(); } private: - sp mCC; - CpuConsumer::LockedBuffer mBuffer; + sp mOutBuffer; + uint8_t* mPixels = NULL; }; class LayerTransactionTest : public ::testing::Test { @@ -858,21 +823,17 @@ TEST_F(LayerTransactionTest, SetFlagsSecure) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); sp composer = ComposerService::getComposerService(); - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - + sp outBuffer; Transaction() .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) .apply(true); ASSERT_EQ(PERMISSION_DENIED, - composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); ASSERT_EQ(NO_ERROR, - composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); } @@ -1504,7 +1465,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { } } -class LayerUpdateTest : public ::testing::Test { +class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { mComposerClient = new SurfaceComposerClient; @@ -2318,12 +2279,12 @@ TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { class ScreenCaptureTest : public LayerUpdateTest { protected: - std::unique_ptr mCapture; + std::unique_ptr mCapture; }; TEST_F(ScreenCaptureTest, CaptureSingleLayer) { auto bgHandle = mBGSurfaceControl->getHandle(); - CaptureLayer::captureScreen(&mCapture, bgHandle); + ScreenCapture::captureLayers(&mCapture, bgHandle); mCapture->expectBGColor(0, 0); // Doesn't capture FG layer which is at 64, 64 mCapture->expectBGColor(64, 64); @@ -2340,7 +2301,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { SurfaceComposerClient::Transaction().show(child).apply(true); // Captures mFGSurfaceControl layer and its child. - CaptureLayer::captureScreen(&mCapture, fgHandle); + ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); } @@ -2365,7 +2326,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { .apply(true); // Captures mFGSurfaceControl, its child, and the grandchild. - CaptureLayer::captureScreen(&mCapture, fgHandle); + ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); mCapture->checkPixel(5, 5, 50, 50, 50); @@ -2381,7 +2342,7 @@ TEST_F(ScreenCaptureTest, CaptureChildOnly) { SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true); // Captures only the child layer, and not the parent. - CaptureLayer::captureScreen(&mCapture, childHandle); + ScreenCapture::captureLayers(&mCapture, childHandle); mCapture->expectChildColor(0, 0); mCapture->expectChildColor(9, 9); } @@ -2407,94 +2368,96 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { auto grandchildHandle = grandchild->getHandle(); // Captures only the grandchild. - CaptureLayer::captureScreen(&mCapture, grandchildHandle); + ScreenCapture::captureLayers(&mCapture, grandchildHandle); mCapture->checkPixel(0, 0, 50, 50, 50); mCapture->checkPixel(4, 4, 50, 50, 50); } TEST_F(ScreenCaptureTest, CaptureCrop) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = mComposerClient->createSurface( - String8("Blue surface"), - 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = + mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, + 0, redLayer.get()); - fillSurfaceRGBA8(redLayer, 255, 0, 0); - fillSurfaceRGBA8(blueLayer, 0, 0, 255); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX-1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX - 1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - CaptureLayer::captureScreen(&mCapture, redLayerHandle); - mCapture->checkPixel(29, 29, 0, 0, 255); - mCapture->checkPixel(30, 30, 255, 0, 0); + ScreenCapture::captureLayers(&mCapture, redLayerHandle); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); Rect crop = Rect(0, 0, 30, 30); - CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop); + ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop); // Capturing the cropped screen, cropping out the shown red area, should leave only the blue // area visible. - mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureSize) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = mComposerClient->createSurface( - String8("Blue surface"), - 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = + mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, + 0, redLayer.get()); - fillSurfaceRGBA8(redLayer, 255, 0, 0); - fillSurfaceRGBA8(blueLayer, 0, 0, 255); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX-1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX - 1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - CaptureLayer::captureScreen(&mCapture, redLayerHandle); - mCapture->checkPixel(29, 29, 0, 0, 255); - mCapture->checkPixel(30, 30, 255, 0, 0); - - CaptureLayer::captureScreen(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); + ScreenCapture::captureLayers(&mCapture, redLayerHandle); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); + + ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. - mCapture->checkPixel(14, 14, 0, 0, 255); - mCapture->checkPixel(15, 15, 255, 0, 0); - mCapture->checkPixel(29, 29, 255, 0, 0); + mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); - fillSurfaceRGBA8(redLayer, 255, 0, 0); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); auto redLayerHandle = redLayer->getHandle(); mComposerClient->destroySurface(redLayerHandle); SurfaceComposerClient::Transaction().apply(true); - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - sp sf(ComposerService::getComposerService()); + sp outBuffer; // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND - ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0)); + sp sf(ComposerService::getComposerService()); + ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); } -} \ No newline at end of file +} // namespace android -- cgit v1.2.3-59-g8ed1b From 8ea97bbe9b5097feaa76926c6ac49120e0fc3649 Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 29 Nov 2017 10:05:15 -0800 Subject: Remove from top layer list if re-parenting top layer. If a layer is given a parent when it originally didn't have one, remove the layer from the top layer list. This is to ensure the layer isn't in duplicate places and that it can get properly cleaned up. Test: Transaction_test#ReparentFromNoParent successfully removes layer when test completes. Change-Id: I1f1c4ee386626c1ef2e3a2e50324ec336d234d5b --- services/surfaceflinger/SurfaceFlinger.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d81178c559..f29d98008c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3224,7 +3224,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( // changed, we don't want this to cause any more work } if (what & layer_state_t::eReparent) { + bool hadParent = layer->hasParent(); if (layer->reparent(s.parentHandleForChild)) { + if (!hadParent) { + mCurrentState.layersSortedByZ.remove(layer); + } flags |= eTransactionNeeded|eTraversalNeeded; } } -- cgit v1.2.3-59-g8ed1b From 707b8f3507fa4a3915844c7a4730e67f94eee2f7 Mon Sep 17 00:00:00 2001 From: Chavi Weingarten Date: Wed, 29 Nov 2017 21:25:51 +0000 Subject: Revert "Use GraphicBuffer instead of GBP for screenshots." This reverts commit a252d895816b3aa6c3bc2b2083113694ead6963d. Reason for revert: SystemUI and some other places need to be updated as well. Will resubmit with the other necessary changes Change-Id: I2dfb7b439c866f31ffa584e450d3208c75afecaa Bug: 69898957 --- libs/gui/ISurfaceComposer.cpp | 71 +++---- libs/gui/Surface.cpp | 21 -- libs/gui/SurfaceComposerClient.cpp | 174 +++++++++++++++- libs/gui/include/gui/ISurfaceComposer.h | 15 +- libs/gui/include/gui/Surface.h | 2 - libs/gui/include/gui/SurfaceComposerClient.h | 72 ++++++- libs/gui/tests/Surface_test.cpp | 13 +- services/surfaceflinger/SurfaceFlinger.cpp | 112 +++++++--- services/surfaceflinger/SurfaceFlinger.h | 18 +- services/surfaceflinger/tests/Transaction_test.cpp | 229 ++++++++++++--------- 10 files changed, 500 insertions(+), 227 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 5de84ecbab..c21c5e3eb8 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -100,13 +100,17 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - virtual status_t captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - ISurfaceComposer::Rotation rotation) { + virtual status_t captureScreen(const sp& display, + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, + ISurfaceComposer::Rotation rotation) + { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); + data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); @@ -114,45 +118,21 @@ public: data.writeInt32(maxLayerZ); data.writeInt32(static_cast(useIdentityTransform)); data.writeInt32(static_cast(rotation)); - status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); - - if (err != NO_ERROR) { - return err; - } - - err = reply.readInt32(); - if (err != NO_ERROR) { - return err; - } - - *outBuffer = new GraphicBuffer(); - reply.read(**outBuffer); - return err; + remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); + return reply.readInt32(); } virtual status_t captureLayers(const sp& layerHandleBinder, - sp* outBuffer, const Rect& sourceCrop, - float frameScale) { + const sp& producer, + const Rect& sourceCrop, float frameScale) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); + data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeFloat(frameScale); - status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); - - if (err != NO_ERROR) { - return err; - } - - err = reply.readInt32(); - if (err != NO_ERROR) { - return err; - } - - *outBuffer = new GraphicBuffer(); - reply.read(**outBuffer); - - return err; + remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); + return reply.readInt32(); } virtual bool authenticateSurfaceTexture( @@ -603,7 +583,8 @@ status_t BnSurfaceComposer::onTransact( case CAPTURE_SCREEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); - sp outBuffer; + sp producer = + interface_cast(data.readStrongBinder()); Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); uint32_t reqWidth = data.readUint32(); @@ -613,28 +594,24 @@ status_t BnSurfaceComposer::onTransact( bool useIdentityTransform = static_cast(data.readInt32()); int32_t rotation = data.readInt32(); - status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, - static_cast(rotation)); + status_t res = captureScreen(display, producer, + sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, + useIdentityTransform, + static_cast(rotation)); reply->writeInt32(res); - if (res == NO_ERROR) { - reply->write(*outBuffer); - } return NO_ERROR; } case CAPTURE_LAYERS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp layerHandleBinder = data.readStrongBinder(); - sp outBuffer; + sp producer = + interface_cast(data.readStrongBinder()); Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); float frameScale = data.readFloat(); - status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale); + status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale); reply->writeInt32(res); - if (res == NO_ERROR) { - reply->write(*outBuffer); - } return NO_ERROR; } case AUTHENTICATE_SURFACE: { diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 80216bc63e..e9393831c7 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1760,25 +1760,4 @@ status_t Surface::getAndFlushRemovedBuffers(std::vector>* out) return OK; } -status_t Surface::attachAndQueueBuffer(Surface* surface, sp buffer) { - if (buffer == nullptr) { - return BAD_VALUE; - } - int err = static_cast(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT, - NATIVE_WINDOW_API_CPU); - if (err != OK) { - return err; - } - err = surface->attachBuffer(buffer->getNativeBuffer()); - if (err != OK) { - return err; - } - err = static_cast(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1); - if (err != OK) { - return err; - } - err = surface->disconnect(NATIVE_WINDOW_API_CPU); - return err; -} - }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0dbe786f1a..2466d2555a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -717,27 +717,181 @@ status_t SurfaceComposerClient::getHdrCapabilities(const sp& display, // ---------------------------------------------------------------------------- -status_t ScreenshotClient::capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, - uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation, - sp* outBuffer) { +status_t ScreenshotClient::capture( + const sp& display, + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ, - maxLayerZ, useIdentityTransform, - static_cast(rotation)); + return s->captureScreen(display, producer, sourceCrop, + reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform); +} + +status_t ScreenshotClient::captureToBuffer(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + uint32_t rotation, + sp* outBuffer) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + + sp gbpConsumer; + sp producer; + BufferQueue::createBufferQueue(&producer, &gbpConsumer); + sp consumer(new BufferItemConsumer(gbpConsumer, + GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER, + 1, true)); + + status_t ret = s->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight, + minLayerZ, maxLayerZ, useIdentityTransform, + static_cast(rotation)); if (ret != NO_ERROR) { return ret; } + BufferItem b; + consumer->acquireBuffer(&b, 0, true); + *outBuffer = b.mGraphicBuffer; return ret; } -status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect sourceCrop, - float frameScale, sp* outBuffer) { +status_t ScreenshotClient::captureLayers(const sp& layerHandle, + const sp& producer, + Rect sourceCrop, float frameScale) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale); + return s->captureLayers(layerHandle, producer, sourceCrop, frameScale); +} + +status_t ScreenshotClient::captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + + sp gbpConsumer; + sp producer; + BufferQueue::createBufferQueue(&producer, &gbpConsumer); + sp consumer(new BufferItemConsumer(gbpConsumer, + GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_SW_READ_NEVER | + GRALLOC_USAGE_SW_WRITE_NEVER, + 1, true)); + + status_t ret = s->captureLayers(layerHandle, producer, sourceCrop, frameScale); + if (ret != NO_ERROR) { + return ret; + } + BufferItem b; + consumer->acquireBuffer(&b, 0, true); + *outBuffer = b.mGraphicBuffer; return ret; } + +ScreenshotClient::ScreenshotClient() + : mHaveBuffer(false) { + memset(&mBuffer, 0, sizeof(mBuffer)); +} + +ScreenshotClient::~ScreenshotClient() { + ScreenshotClient::release(); +} + +sp ScreenshotClient::getCpuConsumer() const { + if (mCpuConsumer == NULL) { + sp consumer; + BufferQueue::createBufferQueue(&mProducer, &consumer); + mCpuConsumer = new CpuConsumer(consumer, 1); + mCpuConsumer->setName(String8("ScreenshotClient")); + } + return mCpuConsumer; +} + +status_t ScreenshotClient::update(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + sp cpuConsumer = getCpuConsumer(); + + if (mHaveBuffer) { + mCpuConsumer->unlockBuffer(mBuffer); + memset(&mBuffer, 0, sizeof(mBuffer)); + mHaveBuffer = false; + } + + status_t err = s->captureScreen(display, mProducer, sourceCrop, + reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, + static_cast(rotation)); + + if (err == NO_ERROR) { + err = mCpuConsumer->lockNextBuffer(&mBuffer); + if (err == NO_ERROR) { + mHaveBuffer = true; + } + } + return err; +} + +status_t ScreenshotClient::update(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform) { + + return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, + minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone); +} + +status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, + bool useIdentityTransform) { + return ScreenshotClient::update(display, sourceCrop, 0, 0, + INT32_MIN, INT32_MAX, + useIdentityTransform, ISurfaceComposer::eRotateNone); +} + +status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) { + return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, + INT32_MIN, INT32_MAX, + useIdentityTransform, ISurfaceComposer::eRotateNone); +} + +void ScreenshotClient::release() { + if (mHaveBuffer) { + mCpuConsumer->unlockBuffer(mBuffer); + memset(&mBuffer, 0, sizeof(mBuffer)); + mHaveBuffer = false; + } + mCpuConsumer.clear(); +} + +void const* ScreenshotClient::getPixels() const { + return mBuffer.data; +} + +uint32_t ScreenshotClient::getWidth() const { + return mBuffer.width; +} + +uint32_t ScreenshotClient::getHeight() const { + return mBuffer.height; +} + +PixelFormat ScreenshotClient::getFormat() const { + return mBuffer.format; +} + +uint32_t ScreenshotClient::getStride() const { + return mBuffer.stride; +} + +size_t ScreenshotClient::getSize() const { + return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format); +} + +android_dataspace ScreenshotClient::getDataSpace() const { + return mBuffer.dataSpace; +} + // ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index e26e332589..1e4c329e1e 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -29,7 +29,6 @@ #include #include -#include #include @@ -168,14 +167,16 @@ public: /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. */ - virtual status_t captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - Rotation rotation = eRotateNone) = 0; + virtual status_t captureScreen(const sp& display, + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, + Rotation rotation = eRotateNone) = 0; virtual status_t captureLayers(const sp& layerHandleBinder, - sp* outBuffer, const Rect& sourceCrop, - float frameScale = 1.0) = 0; + const sp& producer, + const Rect& sourceCrop, float frameScale = 1.0) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 354f23ab06..3fe29d955b 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -283,8 +283,6 @@ public: android_dataspace_t getBuffersDataSpace(); - static status_t attachAndQueueBuffer(Surface* surface, sp buffer); - protected: enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 3f13946339..b0fa922cd9 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -279,16 +279,74 @@ private: // --------------------------------------------------------------------------- -class ScreenshotClient { +class ScreenshotClient +{ public: // if cropping isn't required, callers may pass in a default Rect, e.g.: // capture(display, producer, Rect(), reqWidth, ...); - static status_t capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, - uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation, - sp* outBuffer); - static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float fameScale, - sp* outBuffer); + static status_t capture( + const sp& display, + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform); + static status_t captureToBuffer( + const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, + uint32_t rotation, + sp* outbuffer); + + static status_t captureLayers(const sp& layerHandle, + const sp& producer, Rect sourceCrop, + float frameScale); + static status_t captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer); + +private: + mutable sp mCpuConsumer; + mutable sp mProducer; + CpuConsumer::LockedBuffer mBuffer; + bool mHaveBuffer; + +public: + ScreenshotClient(); + ~ScreenshotClient(); + + // frees the previous screenshot and captures a new one + // if cropping isn't required, callers may pass in a default Rect, e.g.: + // update(display, Rect(), useIdentityTransform); + status_t update(const sp& display, + Rect sourceCrop, bool useIdentityTransform); + status_t update(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + bool useIdentityTransform); + status_t update(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform); + status_t update(const sp& display, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation); + + sp getCpuConsumer() const; + + // release memory occupied by the screenshot + void release(); + + // pixels are valid until this object is freed or + // release() or update() is called + void const* getPixels() const; + + uint32_t getWidth() const; + uint32_t getHeight() const; + PixelFormat getFormat() const; + uint32_t getStride() const; + // size of allocated memory in bytes + size_t getSize() const; + android_dataspace getDataSpace() const; }; // --------------------------------------------------------------------------- diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 470a338639..ac4eb0cb1d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -116,11 +116,14 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { sp anw(mSurface); // Verify the screenshot works with no protected buffers. + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay( ISurfaceComposer::eDisplayIdMain)); - sp outBuffer; - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), 64, 64, 0, 0x7fffffff, false)); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), @@ -151,7 +154,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { &buf)); ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), 64, 64, 0, 0x7fffffff, false)); } @@ -521,13 +524,13 @@ public: status_t setActiveColorMode(const sp& /*display*/, android_color_mode_t /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp& /*display*/, - sp* /*outBuffer*/, + const sp& /*producer*/, Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/, bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, - sp* /*outBuffer*/, + const sp& /*producer*/, const Rect& /*sourceCrop*/, float /*frameScale*/) override { return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4acd448293..d81178c559 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4339,10 +4339,44 @@ private: const int mApi; }; -status_t SurfaceFlinger::captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, +static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth, + uint32_t requestedHeight, bool hasWideColorDisplay, + bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) { + const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; + + int err = 0; + err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight); + err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); + err |= native_window_set_usage(window, usage); + + if (hasWideColorDisplay) { + err |= native_window_set_buffers_data_space(window, + renderEngineUsesWideColor + ? HAL_DATASPACE_DISPLAY_P3 + : HAL_DATASPACE_V0_SRGB); + } + + if (err != NO_ERROR) { + return BAD_VALUE; + } + + /* TODO: Once we have the sync framework everywhere this can use + * server-side waits on the fence that dequeueBuffer returns. + */ + err = native_window_dequeue_buffer_and_wait(window, outBuffer); + if (err != NO_ERROR) { + return err; + } + + return NO_ERROR; +} + +status_t SurfaceFlinger::captureScreen(const sp& display, + const sp& producer, Rect sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, + int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); @@ -4353,18 +4387,18 @@ status_t SurfaceFlinger::captureScreen(const sp& display, sp& layerHandleBinder, - sp* outBuffer, const Rect& sourceCrop, - float frameScale) { + const sp& producer, + const Rect& sourceCrop, float frameScale) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: LayerRenderArea(const sp& layer, const Rect crop, int32_t reqWidth, - int32_t reqHeight) + int32_t reqHeight) : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} const Transform& getTransform() const override { // Make the top level transform the inverse the transform and it's parent so it sets @@ -4427,21 +4461,51 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, visitor(layer); }); }; - return captureScreenCommon(renderArea, traverseLayers, outBuffer, false); + return captureScreenCommon(renderArea, traverseLayers, producer, false); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - sp* outBuffer, + const sp& producer, bool useIdentityTransform) { ATRACE_CALL(); + if (CC_UNLIKELY(producer == 0)) + return BAD_VALUE; + renderArea.updateDimensions(); - const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(), - HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot"); + // if we have secure windows on this display, never allow the screen capture + // unless the producer interface is local (i.e.: we can take a screenshot for + // ourselves). + bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder(); + + // create a surface (because we're a producer, and we need to + // dequeue/queue a buffer) + sp surface = new Surface(producer, false); + + // Put the screenshot Surface into async mode so that + // Layer::headFenceHasSignaled will always return true and we'll latch the + // first buffer regardless of whether or not its acquire fence has + // signaled. This is needed to avoid a race condition in the rotation + // animation. See b/30209608 + surface->setAsyncMode(true); + + ANativeWindow* window = surface.get(); + + status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); + if (result != NO_ERROR) { + return result; + } + WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL); + + ANativeWindowBuffer* buffer = nullptr; + result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(), + hasWideColorDisplay && !mForceNativeColorMode, + getRenderEngine().usesWideColor(), &buffer); + if (result != NO_ERROR) { + return result; + } // This mutex protects syncFd and captureResult for communication of the return values from the // main thread back to this Binder thread @@ -4466,8 +4530,8 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, int fd = -1; { Mutex::Autolock _l(mStateLock); - result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), - useIdentityTransform, &fd); + result = captureScreenImplLocked(renderArea, traverseLayers, buffer, + useIdentityTransform, isLocalScreenshot, &fd); } { @@ -4478,7 +4542,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } }); - status_t result = postMessageAsync(message); + result = postMessageAsync(message); if (result == NO_ERROR) { captureCondition.wait(captureLock, [&]() { return captureResult; }); while (*captureResult == EAGAIN) { @@ -4493,10 +4557,9 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } if (result == NO_ERROR) { - sync_wait(syncFd, -1); - close(syncFd); + // queueBuffer takes ownership of syncFd + result = window->queueBuffer(window, buffer, syncFd); } - return result; } @@ -4539,8 +4602,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, } engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode); - engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE - : renderArea.getActiveColorMode()); + engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode()); // make sure to clear all GL error flags engine.checkErrors(); @@ -4583,7 +4645,7 @@ private: status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, - bool useIdentityTransform, + bool useIdentityTransform, bool isLocalScreenshot, int* outSyncFd) { ATRACE_CALL(); @@ -4593,7 +4655,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure()); }); - if (secureLayerIsVisible) { + if (!isLocalScreenshot && secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); return PERMISSION_DENIED; } @@ -4742,4 +4804,4 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" -#endif \ No newline at end of file +#endif diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a01d353a70..f61dc756c2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -291,11 +291,13 @@ private: std::vector* outSupported) const; virtual sp createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp); - virtual status_t captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - ISurfaceComposer::Rotation rotation); - virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, + virtual status_t captureScreen(const sp& display, + const sp& producer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, ISurfaceComposer::Rotation rotation); + virtual status_t captureLayers(const sp& parentHandle, + const sp& producer, const Rect& sourceCrop, float frameScale); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); @@ -434,13 +436,15 @@ private: void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, bool yswap, bool useIdentityTransform); + status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - sp* outBuffer, + const sp& producer, bool useIdentityTransform); + status_t captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, - int* outSyncFd); + bool isLocalScreenshot, int* outSyncFd); void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index ff81dc9461..39aef8164c 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -104,22 +104,20 @@ void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const } // Check if a region has the specified color. -void expectBufferColor(const sp& outBuffer, uint8_t* pixels, const Rect& rect, +void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect, const Color& color, uint8_t tolerance) { int32_t x = rect.left; int32_t y = rect.top; int32_t width = rect.right - rect.left; int32_t height = rect.bottom - rect.top; - int32_t bufferWidth = int32_t(outBuffer->getWidth()); - int32_t bufferHeight = int32_t(outBuffer->getHeight()); - if (x + width > bufferWidth) { - x = std::min(x, bufferWidth); - width = bufferWidth - x; + if (x + width > int32_t(buffer.width)) { + x = std::min(x, int32_t(buffer.width)); + width = buffer.width - x; } - if (y + height > bufferHeight) { - y = std::min(y, bufferHeight); - height = bufferHeight - y; + if (y + height > int32_t(buffer.height)) { + y = std::min(y, int32_t(buffer.height)); + height = buffer.height - y; } auto colorCompare = [tolerance](uint8_t a, uint8_t b) { @@ -127,7 +125,8 @@ void expectBufferColor(const sp& outBuffer, uint8_t* pixels, cons return tmp <= tolerance; }; for (int32_t j = 0; j < height; j++) { - const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; + const uint8_t* src = + static_cast(buffer.data) + (buffer.stride * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) @@ -171,38 +170,30 @@ class ScreenCapture : public RefBase { public: static void captureScreen(sp* sc, int32_t minLayerZ = 0, int32_t maxLayerZ = std::numeric_limits::max()) { + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); SurfaceComposerClient::Transaction().apply(true); - sp outBuffer; ASSERT_EQ(NO_ERROR, - sf->captureScreen(display, &outBuffer, Rect(), 0, 0, minLayerZ, maxLayerZ, - false)); - *sc = new ScreenCapture(outBuffer); - } - - static void captureLayers(std::unique_ptr* sc, sp& parentHandle, - Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { - sp sf(ComposerService::getComposerService()); - SurfaceComposerClient::Transaction().apply(true); - - sp outBuffer; - ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale)); - *sc = std::make_unique(outBuffer); + sf->captureScreen(display, producer, Rect(), 0, 0, minLayerZ, maxLayerZ, false)); + *sc = new ScreenCapture(cpuConsumer); } void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); - expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); + expectBufferColor(mBuf, rect, color, tolerance); } void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); const bool leftBorder = rect.left > 0; const bool topBorder = rect.top > 0; - const bool rightBorder = rect.right < int32_t(mOutBuffer->getWidth()); - const bool bottomBorder = rect.bottom < int32_t(mOutBuffer->getHeight()); + const bool rightBorder = rect.right < int32_t(mBuf.width); + const bool bottomBorder = rect.bottom < int32_t(mBuf.height); if (topBorder) { Rect top(rect.left, rect.top - 1, rect.right, rect.top); @@ -255,8 +246,9 @@ public: } void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); - const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x)); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); + const uint8_t* img = static_cast(mBuf.data); + const uint8_t* pixel = img + (4 * (y * mBuf.stride + x)); if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { String8 err(String8::format("pixel @ (%3d, %3d): " "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", @@ -271,15 +263,58 @@ public: void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } - ScreenCapture(const sp& outBuffer) : mOutBuffer(outBuffer) { - mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast(&mPixels)); +private: + ScreenCapture(const sp& cc) : mCC(cc) { + EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf)); } - ~ScreenCapture() { mOutBuffer->unlock(); } + ~ScreenCapture() { mCC->unlockBuffer(mBuf); } + + sp mCC; + CpuConsumer::LockedBuffer mBuf; +}; + +class CaptureLayer { +public: + static void captureScreen(std::unique_ptr* sc, sp& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); + sp sf(ComposerService::getComposerService()); + SurfaceComposerClient::Transaction().apply(true); + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale)); + *sc = std::make_unique(cpuConsumer); + } + + void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuffer.format); + const uint8_t* img = static_cast(mBuffer.data); + const uint8_t* pixel = img + (4 * (y * mBuffer.stride + x)); + if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { + String8 err(String8::format("pixel @ (%3d, %3d): " + "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", + x, y, r, g, b, pixel[0], pixel[1], pixel[2])); + EXPECT_EQ(String8(), err) << err.string(); + } + } + + void expectFGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 195, 63, 63); } + + void expectBGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 63, 63, 195); } + + void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } + + CaptureLayer(const sp& cc) : mCC(cc) { + EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuffer)); + } + + ~CaptureLayer() { mCC->unlockBuffer(mBuffer); } private: - sp mOutBuffer; - uint8_t* mPixels = NULL; + sp mCC; + CpuConsumer::LockedBuffer mBuffer; }; class LayerTransactionTest : public ::testing::Test { @@ -823,17 +858,21 @@ TEST_F(LayerTransactionTest, SetFlagsSecure) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); sp composer = ComposerService::getComposerService(); - sp outBuffer; + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); + Transaction() .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) .apply(true); ASSERT_EQ(PERMISSION_DENIED, - composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); ASSERT_EQ(NO_ERROR, - composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); } @@ -1465,7 +1504,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { } } -class LayerUpdateTest : public LayerTransactionTest { +class LayerUpdateTest : public ::testing::Test { protected: virtual void SetUp() { mComposerClient = new SurfaceComposerClient; @@ -2279,12 +2318,12 @@ TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { class ScreenCaptureTest : public LayerUpdateTest { protected: - std::unique_ptr mCapture; + std::unique_ptr mCapture; }; TEST_F(ScreenCaptureTest, CaptureSingleLayer) { auto bgHandle = mBGSurfaceControl->getHandle(); - ScreenCapture::captureLayers(&mCapture, bgHandle); + CaptureLayer::captureScreen(&mCapture, bgHandle); mCapture->expectBGColor(0, 0); // Doesn't capture FG layer which is at 64, 64 mCapture->expectBGColor(64, 64); @@ -2301,7 +2340,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { SurfaceComposerClient::Transaction().show(child).apply(true); // Captures mFGSurfaceControl layer and its child. - ScreenCapture::captureLayers(&mCapture, fgHandle); + CaptureLayer::captureScreen(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); } @@ -2326,7 +2365,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { .apply(true); // Captures mFGSurfaceControl, its child, and the grandchild. - ScreenCapture::captureLayers(&mCapture, fgHandle); + CaptureLayer::captureScreen(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); mCapture->checkPixel(5, 5, 50, 50, 50); @@ -2342,7 +2381,7 @@ TEST_F(ScreenCaptureTest, CaptureChildOnly) { SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true); // Captures only the child layer, and not the parent. - ScreenCapture::captureLayers(&mCapture, childHandle); + CaptureLayer::captureScreen(&mCapture, childHandle); mCapture->expectChildColor(0, 0); mCapture->expectChildColor(9, 9); } @@ -2368,96 +2407,94 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { auto grandchildHandle = grandchild->getHandle(); // Captures only the grandchild. - ScreenCapture::captureLayers(&mCapture, grandchildHandle); + CaptureLayer::captureScreen(&mCapture, grandchildHandle); mCapture->checkPixel(0, 0, 50, 50, 50); mCapture->checkPixel(4, 4, 50, 50, 50); } TEST_F(ScreenCaptureTest, CaptureCrop) { - sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, - PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = - mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, - 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = mComposerClient->createSurface( + String8("Blue surface"), + 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); + fillSurfaceRGBA8(redLayer, 255, 0, 0); + fillSurfaceRGBA8(blueLayer, 0, 0, 255); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX - 1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX-1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - ScreenCapture::captureLayers(&mCapture, redLayerHandle); - mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); - // red area below the blue area - mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); - // red area to the right of the blue area - mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); + CaptureLayer::captureScreen(&mCapture, redLayerHandle); + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 255, 0, 0); Rect crop = Rect(0, 0, 30, 30); - ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop); + CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop); // Capturing the cropped screen, cropping out the shown red area, should leave only the blue // area visible. - mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + mCapture->checkPixel(29, 29, 0, 0, 255); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureSize) { - sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, - PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = - mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, - 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = mComposerClient->createSurface( + String8("Blue surface"), + 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); + fillSurfaceRGBA8(redLayer, 255, 0, 0); + fillSurfaceRGBA8(blueLayer, 0, 0, 255); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX - 1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX-1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - ScreenCapture::captureLayers(&mCapture, redLayerHandle); - mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); - // red area below the blue area - mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); - // red area to the right of the blue area - mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); - - ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); + CaptureLayer::captureScreen(&mCapture, redLayerHandle); + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 255, 0, 0); + + CaptureLayer::captureScreen(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. - mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE); - // red area below the blue area - mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED); - // red area to the right of the blue area - mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED); + mCapture->checkPixel(14, 14, 0, 0, 255); + mCapture->checkPixel(15, 15, 255, 0, 0); + mCapture->checkPixel(29, 29, 255, 0, 0); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { - sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, - PIXEL_FORMAT_RGBA_8888, 0); + sp redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + fillSurfaceRGBA8(redLayer, 255, 0, 0); auto redLayerHandle = redLayer->getHandle(); mComposerClient->destroySurface(redLayerHandle); SurfaceComposerClient::Transaction().apply(true); - sp outBuffer; + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp cpuConsumer = new CpuConsumer(consumer, 1); + sp sf(ComposerService::getComposerService()); // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND - sp sf(ComposerService::getComposerService()); - ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); + ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0)); } -} // namespace android +} \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From d4d9c6fc5616ace39b2c3f23e4590ea8373d3fcf Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Nov 2017 16:55:31 -0800 Subject: surfaceflinger: move EGL initialization into RE This defers EGL initialization a bit, from before EventThread initialization to after. Test: SurfaceFlinger_test Change-Id: Icbe9b78d1db189ce5e6aeedf902fe7b62ea2004e --- services/surfaceflinger/RenderEngine/RenderEngine.cpp | 9 +++++++-- services/surfaceflinger/RenderEngine/RenderEngine.h | 3 +-- services/surfaceflinger/SurfaceFlinger.cpp | 14 ++++---------- 3 files changed, 12 insertions(+), 14 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 5b6ff42a12..9f94e13ef5 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -47,8 +47,13 @@ static bool findExtension(const char* exts, const char* name) { return false; } -std::unique_ptr RenderEngine::create(EGLDisplay display, - int hwcFormat, uint32_t featureFlags) { +std::unique_ptr RenderEngine::create(int hwcFormat, uint32_t featureFlags) { + // initialize EGL for the default display + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (!eglInitialize(display, NULL, NULL)) { + LOG_ALWAYS_FATAL("failed to initialize EGL"); + } + // EGL_ANDROIDX_no_config_context is an experimental extension with no // written specification. It will be replaced by something more formal. // SurfaceFlinger is using it to allow a single EGLContext to render to diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index b4839bead6..b28454a99d 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -67,8 +67,7 @@ public: enum FeatureFlag { WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display }; - static std::unique_ptr create(EGLDisplay display, - int hwcFormat, uint32_t featureFlags); + static std::unique_ptr create(int hwcFormat, uint32_t featureFlags); static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 59ac0ecd3e..815944e9b7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -594,10 +594,6 @@ void SurfaceFlinger::init() { Mutex::Autolock _l(mStateLock); - // initialize EGL for the default display - mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(mEGLDisplay, NULL, NULL); - // start the EventThread sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app"); @@ -618,16 +614,14 @@ void SurfaceFlinger::init() { } // Get a RenderEngine for the given display / config (can't fail) - mRenderEngine = RenderEngine::create(mEGLDisplay, - HAL_PIXEL_FORMAT_RGBA_8888, + mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0); + LOG_ALWAYS_FATAL_IF(mRenderEngine == nullptr, "couldn't create RenderEngine"); - // retrieve the EGL context that was selected/created + // retrieve the EGL display/context that was selected/created + mEGLDisplay = mRenderEngine->getEGLDisplay(); 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)); -- cgit v1.2.3-59-g8ed1b From b01450b71d7d335f72904ca5ee8d3e1e1fc08bcc Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Nov 2017 16:55:31 -0800 Subject: surfaceflinger: move EGL termination into RE This defers EGL termination a bit but that should be fine. More importantly, SurfaceFlinger is never destructed. Test: SurfaceFlinger_test Change-Id: I200e2169eb1cc419a587a7626b438d3d5ddedc70 --- services/surfaceflinger/RenderEngine/RenderEngine.cpp | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 9f94e13ef5..ac646ac6fe 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -165,6 +165,8 @@ RenderEngine::RenderEngine() : mEGLDisplay(EGL_NO_DISPLAY), mEGLConfig(NULL), } RenderEngine::~RenderEngine() { + eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglTerminate(mEGLDisplay); } void RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 815944e9b7..f3d3866a65 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -285,9 +285,6 @@ void SurfaceFlinger::onFirstRef() SurfaceFlinger::~SurfaceFlinger() { - EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglTerminate(display); } void SurfaceFlinger::binderDied(const wp& /* who */) -- cgit v1.2.3-59-g8ed1b From 8601f886d506886d72767979c12f393cbcd2a2cd Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Nov 2017 16:52:21 -0800 Subject: surfaceflinger: move EGL version/extensions dump into RE Test: SurfaceFlinger_test Change-Id: I0c6e258e5ab2e55c7092d1642627c573038b99ac --- services/surfaceflinger/RenderEngine/RenderEngine.cpp | 5 +++++ services/surfaceflinger/SurfaceFlinger.cpp | 9 --------- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index ac646ac6fe..1d22f84570 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -271,6 +271,11 @@ void RenderEngine::readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* } void RenderEngine::dump(String8& result) { + result.appendFormat("EGL implementation : %s\n", + eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION)); + result.appendFormat("%s\n", + eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS)); + const GLExtensions& extensions(GLExtensions::getInstance()); result.appendFormat("GLES: %s, %s, %s\n", extensions.getVendor(), diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f3d3866a65..4c177231f8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -101,8 +101,6 @@ */ #define DEBUG_SCREENSHOTS false -extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); - namespace android { using namespace android::hardware::configstore; @@ -3928,13 +3926,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, HWComposer& hwc(getHwComposer()); sp hw(getDefaultDisplayDeviceLocked()); - colorizer.bold(result); - result.appendFormat("EGL implementation : %s\n", - eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION)); - colorizer.reset(result); - result.appendFormat("%s\n", - eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS)); - mRenderEngine->dump(result); hw->undefinedRegion.dump(result, "undefinedRegion"); -- cgit v1.2.3-59-g8ed1b From 7f40290b223afe1fea1d173da43e8e3d6ae49590 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Nov 2017 12:51:10 -0800 Subject: surfaceflinger: add RenderEngine::setCurrentSurface setCurrentSurface is a wrapper to eglMakeCurrent and it uses the EGL context implied by the RenderEngine. This also allows us to simplify DisplayDevice::makeCurrent. Test: SurfaceFlinger_test Change-Id: Idab581f0ef79af7263159a558d8fad493a198ce7 --- services/surfaceflinger/DisplayDevice.cpp | 6 +++--- services/surfaceflinger/DisplayDevice.h | 2 +- services/surfaceflinger/RenderEngine/RenderEngine.cpp | 8 ++++++++ services/surfaceflinger/RenderEngine/RenderEngine.h | 3 +++ services/surfaceflinger/SurfaceFlinger.cpp | 14 +++++++------- 5 files changed, 22 insertions(+), 11 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index a9f3aa1891..302f0385f8 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -290,14 +290,14 @@ uint32_t DisplayDevice::getFlags() const return mFlags; } -EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const { +EGLBoolean DisplayDevice::makeCurrent() const { EGLBoolean result = EGL_TRUE; EGLSurface sur = eglGetCurrentSurface(EGL_DRAW); if (sur != mSurface) { - result = eglMakeCurrent(dpy, mSurface, mSurface, ctx); + result = mFlinger->getRenderEngine().setCurrentSurface(mSurface); if (result == EGL_TRUE) { if (mType >= DisplayDevice::DISPLAY_VIRTUAL) - eglSwapInterval(dpy, 0); + eglSwapInterval(mDisplay, 0); } } setViewportAndProjection(); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index e388a5b2c3..71aac49863 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -155,7 +155,7 @@ public: void setDisplayName(const String8& displayName); const String8& getDisplayName() const { return mDisplayName; } - EGLBoolean makeCurrent(EGLDisplay dpy, EGLContext ctx) const; + EGLBoolean makeCurrent() const; void setViewportAndProjection() const; const sp& getClientTargetAcquireFence() const; diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 1d22f84570..332f2e0738 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -187,6 +187,14 @@ EGLContext RenderEngine::getEGLContext() const { return mEGLContext; } +bool RenderEngine::setCurrentSurface(EGLSurface surface) { + return eglMakeCurrent(mEGLDisplay, surface, surface, mEGLContext) == EGL_TRUE; +} + +void RenderEngine::resetCurrentSurface() { + eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + void RenderEngine::checkErrors() const { do { // there could be more than one error flag diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index b28454a99d..bd5eac2672 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -99,6 +99,9 @@ public: int getStatus() const; }; + bool setCurrentSurface(EGLSurface surface); + void resetCurrentSurface(); + // set-up virtual void checkErrors() const; virtual void setViewportAndProjection(size_t vpw, size_t vph, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4c177231f8..8d8778841d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1313,7 +1313,7 @@ void SurfaceFlinger::createDefaultDisplayDevice() { // make the GLContext current so that we can create textures when creating // Layers (which may happens before we render something) - hw->makeCurrent(mEGLDisplay, mEGLContext); + hw->makeCurrent(); } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, @@ -1384,7 +1384,7 @@ void SurfaceFlinger::resetDisplayState() { // mCurrentState and mDrawingState and re-apply all changes when we make the // transition. mDrawingState.displays.clear(); - eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + getRenderEngine().resetCurrentSurface(); mDisplays.clear(); } @@ -2041,7 +2041,7 @@ void SurfaceFlinger::postFramebuffer() mHwc->presentAndGetReleaseFences(hwcId); } displayDevice->onSwapBuffersCompleted(); - displayDevice->makeCurrent(mEGLDisplay, mEGLContext); + displayDevice->makeCurrent(); for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { // The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is @@ -2167,7 +2167,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // be sure that nothing associated with this display // is current. const sp defaultDisplay(getDefaultDisplayDeviceLocked()); - defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext); + defaultDisplay->makeCurrent(); sp hw(getDisplayDeviceLocked(draw.keyAt(i))); if (hw != NULL) hw->disconnect(getHwComposer()); @@ -2711,13 +2711,13 @@ bool SurfaceFlinger::doComposeSurfaces( displayDevice->getWideColorSupport() && !mForceNativeColorMode); mRenderEngine->setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode()); - if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) { + if (!displayDevice->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", displayDevice->getDisplayName().string()); - eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + getRenderEngine().resetCurrentSurface(); // |mStateLock| not needed as we are on the main thread - if(!getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext)) { + if(!getDefaultDisplayDeviceLocked()->makeCurrent()) { ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting."); } return false; -- cgit v1.2.3-59-g8ed1b From b0c041b61ef38eb1912b8bb4ff372cf836aa8a30 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Nov 2017 11:36:33 -0800 Subject: surfaceflinger: return fence fd from RenderEngine::flush The caller does not need to work with EGLSync after this chnage. Test: SurfaceFlinger_test Change-Id: I1cf7d11d3023d09be8a73001493c39b4309e7542 --- .../surfaceflinger/RenderEngine/RenderEngine.cpp | 47 +++++++++++++++++++++- .../surfaceflinger/RenderEngine/RenderEngine.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 39 +----------------- 3 files changed, 48 insertions(+), 41 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 332f2e0738..560f74efe4 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -247,8 +247,51 @@ void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, drawMesh(mesh); } -void RenderEngine::flush() { - glFlush(); +int RenderEngine::flush(bool wait) { + // Attempt to create a sync khr object that can produce a sync point. If that + // isn't available, create a non-dupable sync object in the fallback path and + // wait on it directly. + EGLSyncKHR sync; + if (!wait) { + EGLint syncFd = EGL_NO_NATIVE_FENCE_FD_ANDROID; + + sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); + if (sync != EGL_NO_SYNC_KHR) { + // native fence fd will not be populated until flush() is done. + glFlush(); + + // get the sync fd + syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync); + if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { + ALOGW("failed to dup sync khr object"); + } + + eglDestroySyncKHR(mEGLDisplay, sync); + } + + if (syncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID) { + return syncFd; + } + } + + // fallback or explicit wait + sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL); + if (sync != EGL_NO_SYNC_KHR) { + EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, + EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/); + EGLint eglErr = eglGetError(); + if (result == EGL_TIMEOUT_EXPIRED_KHR) { + ALOGW("fence wait timed out"); + } else { + ALOGW_IF(eglErr != EGL_SUCCESS, + "error waiting on EGL fence: %#x", eglErr); + } + eglDestroySyncKHR(mEGLDisplay, sync); + } else { + ALOGW("error creating EGL fence: %#x", eglGetError()); + } + + return -1; } void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) { diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index bd5eac2672..074e97cf17 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -77,7 +77,8 @@ public: virtual void dump(String8& result); // helpers - void flush(); + // flush returns -1 or a valid native fence fd owned by the caller + int flush(bool wait); void clearWithColor(float red, float green, float blue, float alpha); void fillRegionWithColor(const Region& region, uint32_t height, float red, float green, float blue, float alpha); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8d8778841d..c34854b689 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4584,7 +4584,6 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, return PERMISSION_DENIED; } - int syncFd = -1; // create an EGLImage from the buffer so we can later // turn it into a texture EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, @@ -4610,43 +4609,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, // dependent on the context's EGLConfig. renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform); - // Attempt to create a sync khr object that can produce a sync point. If that - // isn't available, create a non-dupable sync object in the fallback path and - // wait on it directly. - EGLSyncKHR sync = EGL_NO_SYNC_KHR; - if (!DEBUG_SCREENSHOTS) { - sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); - // native fence fd will not be populated until flush() is done. - getRenderEngine().flush(); - } - - if (sync != EGL_NO_SYNC_KHR) { - // get the sync fd - syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync); - if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { - ALOGW("captureScreen: failed to dup sync khr object"); - syncFd = -1; - } - eglDestroySyncKHR(mEGLDisplay, sync); - } else { - // fallback path - sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL); - if (sync != EGL_NO_SYNC_KHR) { - EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, - EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/); - EGLint eglErr = eglGetError(); - if (result == EGL_TIMEOUT_EXPIRED_KHR) { - ALOGW("captureScreen: fence wait timed out"); - } else { - ALOGW_IF(eglErr != EGL_SUCCESS, - "captureScreen: error waiting on EGL fence: %#x", eglErr); - } - eglDestroySyncKHR(mEGLDisplay, sync); - } else { - ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError()); - } - } - *outSyncFd = syncFd; + *outSyncFd = getRenderEngine().flush(DEBUG_SCREENSHOTS); if (DEBUG_SCREENSHOTS) { const auto reqWidth = renderArea.getReqWidth(); -- cgit v1.2.3-59-g8ed1b From eadbaa68dbf0f674b2a5260fc813b408cb42fee3 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Nov 2017 11:26:15 -0800 Subject: surfaceflinger: add RenderEngine::BindNativeBufferAsFramebuffer It replaces BindImageAsFramebuffer and makes EGLImage an implementation detail of RenderEngine. Test: SurfaceFlinger_test Change-Id: I01be2d95fb9af9cbefa1a72131afb0975f1e0296 --- .../surfaceflinger/RenderEngine/RenderEngine.cpp | 22 +++++++++--- .../surfaceflinger/RenderEngine/RenderEngine.h | 9 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 39 ++-------------------- 3 files changed, 26 insertions(+), 44 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 560f74efe4..dfd985641f 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -337,21 +337,33 @@ void RenderEngine::dump(String8& result) { // --------------------------------------------------------------------------- -RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer( - RenderEngine& engine, EGLImageKHR image) : mEngine(engine) +RenderEngine::BindNativeBufferAsFramebuffer::BindNativeBufferAsFramebuffer( + RenderEngine& engine, ANativeWindowBuffer* buffer) : mEngine(engine) { - mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus); + mImage = eglCreateImageKHR(mEngine.mEGLDisplay, EGL_NO_CONTEXT, + EGL_NATIVE_BUFFER_ANDROID, buffer, NULL); + if (mImage == EGL_NO_IMAGE_KHR) { + mStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + return; + } + + mEngine.bindImageAsFramebuffer(mImage, &mTexName, &mFbName, &mStatus); ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d", mStatus); } -RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() { +RenderEngine::BindNativeBufferAsFramebuffer::~BindNativeBufferAsFramebuffer() { + if (mImage == EGL_NO_IMAGE_KHR) { + return; + } + // back to main framebuffer mEngine.unbindFramebuffer(mTexName, mFbName); + eglDestroyImageKHR(mEngine.mEGLDisplay, mImage); } -status_t RenderEngine::BindImageAsFramebuffer::getStatus() const { +status_t RenderEngine::BindNativeBufferAsFramebuffer::getStatus() const { return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE; } diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 074e97cf17..2d5bfa3efd 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -31,6 +31,8 @@ #define EGL_NO_CONFIG ((EGLConfig)0) +struct ANativeWindowBuffer; + // --------------------------------------------------------------------------- namespace android { // --------------------------------------------------------------------------- @@ -90,13 +92,14 @@ public: void deleteTextures(size_t count, uint32_t const* names); void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels); - class BindImageAsFramebuffer { + class BindNativeBufferAsFramebuffer { RenderEngine& mEngine; + EGLImageKHR mImage; uint32_t mTexName, mFbName; uint32_t mStatus; public: - BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image); - ~BindImageAsFramebuffer(); + BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer); + ~BindNativeBufferAsFramebuffer(); int getStatus() const; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c34854b689..f139683b59 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4546,26 +4546,6 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, }); } -// A simple RAII class that holds an EGLImage and destroys it either: -// a) When the destroy() method is called -// b) When the object goes out of scope -class ImageHolder { -public: - ImageHolder(EGLDisplay display, EGLImageKHR image) : mDisplay(display), mImage(image) {} - ~ImageHolder() { destroy(); } - - void destroy() { - if (mImage != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(mDisplay, mImage); - mImage = EGL_NO_IMAGE_KHR; - } - } - -private: - const EGLDisplay mDisplay; - EGLImageKHR mImage; -}; - status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, @@ -4584,22 +4564,11 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, return PERMISSION_DENIED; } - // create an EGLImage from the buffer so we can later - // turn it into a texture - EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, - EGL_NATIVE_BUFFER_ANDROID, buffer, NULL); - if (image == EGL_NO_IMAGE_KHR) { - return BAD_VALUE; - } - - // This will automatically destroy the image if we return before calling its destroy method - ImageHolder imageHolder(mEGLDisplay, image); - // this binds the given EGLImage as a framebuffer for the // duration of this scope. - RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image); - if (imageBond.getStatus() != NO_ERROR) { - ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot"); + RenderEngine::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer); + if (bufferBond.getStatus() != NO_ERROR) { + ALOGE("got ANWB binding error while taking screenshot"); return INVALID_OPERATION; } @@ -4621,8 +4590,6 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, delete [] pixels; } - // destroy our image - imageHolder.destroy(); return NO_ERROR; } -- cgit v1.2.3-59-g8ed1b From c670d50b2e1a33ee4e0a8b6967f3e99e03149447 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Nov 2017 23:17:51 -0800 Subject: surfaceflinger: remove EGLConfig from DisplayDevice ctor It is queryable from RenderEngine. Test: SurfaceFlinger_test Change-Id: Id976f831f846b9ff7a5f6d8578cfe1787d55da86 --- services/surfaceflinger/DisplayDevice.cpp | 2 +- services/surfaceflinger/DisplayDevice.h | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 7 ++----- 3 files changed, 3 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 302f0385f8..1bce4e901b 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -88,7 +88,6 @@ DisplayDevice::DisplayDevice( const wp& displayToken, const sp& displaySurface, const sp& producer, - EGLConfig config, bool supportWideColor) : lastCompositionHadVisibleLayers(false), mFlinger(flinger), @@ -121,6 +120,7 @@ DisplayDevice::DisplayDevice( EGLSurface eglSurface; EGLDisplay display = mFlinger->getRenderEngine().getEGLDisplay(); + EGLConfig config = mFlinger->getRenderEngine().getEGLConfig(); if (config == EGL_NO_CONFIG) { config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888, diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 71aac49863..f1581cf4af 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -87,7 +87,6 @@ public: const wp& displayToken, const sp& displaySurface, const sp& producer, - EGLConfig config, bool supportWideColor); // clang-format on diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f139683b59..bdbaf5f78e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1297,8 +1297,7 @@ void SurfaceFlinger::createDefaultDisplayDevice() { } bool useWideColorMode = hasWideColorModes && hasWideColorDisplay && !mForceNativeColorMode; sp hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure, - token, fbs, producer, mRenderEngine->getEGLConfig(), - useWideColorMode); + token, fbs, producer, useWideColorMode); mDisplays.add(token, hw); android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; if (useWideColorMode) { @@ -2285,9 +2284,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (dispSurface != NULL) { sp hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, - dispSurface, producer, - mRenderEngine->getEGLConfig(), - hasWideColorDisplay); + dispSurface, producer, hasWideColorDisplay); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); -- cgit v1.2.3-59-g8ed1b From b523df0c48cefe4b29b5ecbdf1e80c633d3ad36e Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Nov 2017 11:26:15 -0800 Subject: surfaceflinger: remove unused EGL data members Remove SurfaceFlinger::mEGLDisplay and SurfaceFlinger::mEGLContext. With this change, SurfaceFlinger does not use EGL directly anymore. This also allows us to get rid of RenderEngine::getEGLContext. Test: SurfaceFlinger_test Change-Id: I7799d935367650508b741e62a53ce325fdc94234 --- services/surfaceflinger/RenderEngine/RenderEngine.cpp | 4 ---- services/surfaceflinger/RenderEngine/RenderEngine.h | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 6 ------ services/surfaceflinger/SurfaceFlinger.h | 4 ---- 4 files changed, 15 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index dfd985641f..2143c78762 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -183,10 +183,6 @@ EGLConfig RenderEngine::getEGLConfig() const { return mEGLConfig; } -EGLContext RenderEngine::getEGLContext() const { - return mEGLContext; -} - bool RenderEngine::setCurrentSurface(EGLSurface surface) { return eglMakeCurrent(mEGLDisplay, surface, surface, mEGLContext) == EGL_TRUE; } diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 2d5bfa3efd..a3efdf68b0 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -136,7 +136,6 @@ public: EGLDisplay getEGLDisplay() const; EGLConfig getEGLConfig() const; - EGLContext getEGLContext() const; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index bdbaf5f78e..4172d25b26 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -28,8 +28,6 @@ #include #include -#include - #include #include @@ -613,10 +611,6 @@ void SurfaceFlinger::init() { hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0); LOG_ALWAYS_FATAL_IF(mRenderEngine == nullptr, "couldn't create RenderEngine"); - // retrieve the EGL display/context that was selected/created - mEGLDisplay = mRenderEngine->getEGLDisplay(); - mEGLContext = mRenderEngine->getEGLContext(); - LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, "Starting with vr flinger active is not currently supported."); mHwc.reset(new HWComposer(mHwcServiceName)); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2840774cc0..58d999865e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -21,8 +21,6 @@ #include #include -#include - /* * NOTE: Make sure this file doesn't include anything from or */ @@ -667,8 +665,6 @@ private: sp mInjectorEventThread; sp mVSyncInjector; sp mEventControlThread; - EGLContext mEGLContext; - EGLDisplay mEGLDisplay; sp mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; // Can only accessed from the main thread, these members -- cgit v1.2.3-59-g8ed1b From 94e6a688edbf01b44fb4403bc20439326e8f3c3f Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Nov 2017 10:10:23 -0800 Subject: surfaceflinger: remove DisplayDevice::mFlags It is always 0. Test: SurfaceFlinger_test Change-Id: I0a7a53412dbddc9b9a1f0a0c4b521737c59f7d59 --- services/surfaceflinger/DisplayDevice.cpp | 30 +----------------------------- services/surfaceflinger/DisplayDevice.h | 7 ------- services/surfaceflinger/SurfaceFlinger.cpp | 22 +++------------------- 3 files changed, 4 insertions(+), 55 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 1bce4e901b..e454ef76c8 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -53,12 +53,6 @@ using namespace android; // ---------------------------------------------------------------------------- -#ifdef EGL_ANDROID_swap_rectangle -static constexpr bool kEGLAndroidSwapRectangle = true; -#else -static constexpr bool kEGLAndroidSwapRectangle = false; -#endif - // retrieve triple buffer setting from configstore using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; @@ -66,12 +60,6 @@ using namespace android::hardware::configstore::V1_0; static bool useTripleFramebuffer = getInt64< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2) >= 3; -#if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle) -// Dummy implementation in case it is missing. -inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) { -} -#endif - /* * Initialize the display to the specified values. * @@ -99,7 +87,6 @@ DisplayDevice::DisplayDevice( mSurface(EGL_NO_SURFACE), mDisplayWidth(), mDisplayHeight(), - mFlags(), mPageFlipCount(), mIsSecure(isSecure), mLayerStack(NO_LAYER_STACK), @@ -214,19 +201,9 @@ uint32_t DisplayDevice::getPageFlipCount() const { return mPageFlipCount; } -void DisplayDevice::flip(const Region& dirty) const +void DisplayDevice::flip(const Region& /*dirty*/) const { mFlinger->getRenderEngine().checkErrors(); - - if (kEGLAndroidSwapRectangle) { - if (mFlags & SWAP_RECTANGLE) { - const Region newDirty(dirty.intersect(bounds())); - const Rect b(newDirty.getBounds()); - eglSetSwapRectangleANDROID(mDisplay, mSurface, - b.left, b.top, b.width(), b.height()); - } - } - mPageFlipCount++; } @@ -285,11 +262,6 @@ void DisplayDevice::onSwapBuffersCompleted() const { mDisplaySurface->onFrameCommitted(); } -uint32_t DisplayDevice::getFlags() const -{ - return mFlags; -} - EGLBoolean DisplayDevice::makeCurrent() const { EGLBoolean result = EGL_TRUE; EGLSurface sur = eglGetCurrentSurface(EGL_DRAW); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index f1581cf4af..e9cd969f8c 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -69,11 +69,6 @@ public: NUM_BUILTIN_DISPLAY_TYPES = HWC_NUM_PHYSICAL_DISPLAY_TYPES, }; - enum { - PARTIAL_UPDATES = 0x00020000, // video driver feature - SWAP_RECTANGLE = 0x00080000, - }; - enum { NO_LAYER_STACK = 0xFFFFFFFF, }; @@ -106,7 +101,6 @@ public: int getWidth() const; int getHeight() const; - uint32_t getFlags() const; EGLSurface getEGLSurface() const; @@ -203,7 +197,6 @@ private: EGLSurface mSurface; int mDisplayWidth; int mDisplayHeight; - uint32_t mFlags; mutable uint32_t mPageFlipCount; String8 mDisplayName; bool mIsSecure; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4172d25b26..c142f2ff49 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2649,25 +2649,9 @@ void SurfaceFlinger::doDisplayComposition( // compute the invalid region displayDevice->swapRegion.orSelf(dirtyRegion); - uint32_t flags = displayDevice->getFlags(); - if (flags & DisplayDevice::SWAP_RECTANGLE) { - // we can redraw only what's dirty, but since SWAP_RECTANGLE only - // takes a rectangle, we must make sure to update that whole - // rectangle in that case - dirtyRegion.set(displayDevice->swapRegion.bounds()); - } else { - if (flags & DisplayDevice::PARTIAL_UPDATES) { - // We need to redraw the rectangle that will be updated - // (pushed to the framebuffer). - // This is needed because PARTIAL_UPDATES only takes one - // rectangle instead of a region (see DisplayDevice::flip()) - dirtyRegion.set(displayDevice->swapRegion.bounds()); - } else { - // we need to redraw everything (the whole screen) - dirtyRegion.set(displayDevice->bounds()); - displayDevice->swapRegion = dirtyRegion; - } - } + // we need to redraw everything (the whole screen) + dirtyRegion.set(displayDevice->bounds()); + displayDevice->swapRegion = dirtyRegion; if (!doComposeSurfaces(displayDevice, dirtyRegion)) return; -- cgit v1.2.3-59-g8ed1b From b02087dbd6a25e9d077fde16039050da8012b413 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 9 Nov 2017 10:19:54 -0800 Subject: surfaceflinger: remove DisplayDevice::swapRegion With SWAP_RECTANGLE and PARTIAL_UPDATES removed, it becomes clear that swapRegion is not needed. It also becomes clear that DisplayDevice::flip and SurfaceFlinger::doComposeSurfaces do not need the dirty region. Test: SurfaceFlinger_test Change-Id: Id9cd2b43812d3c7dcfa36f605d0f8a647264f228 --- services/surfaceflinger/DisplayDevice.cpp | 2 +- services/surfaceflinger/DisplayDevice.h | 4 +--- services/surfaceflinger/SurfaceFlinger.cpp | 36 +++++++----------------------- services/surfaceflinger/SurfaceFlinger.h | 2 +- 4 files changed, 11 insertions(+), 33 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index e454ef76c8..7aa16dede8 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -201,7 +201,7 @@ uint32_t DisplayDevice::getPageFlipCount() const { return mPageFlipCount; } -void DisplayDevice::flip(const Region& /*dirty*/) const +void DisplayDevice::flip() const { mFlinger->getRenderEngine().checkErrors(); mPageFlipCount++; diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index e9cd969f8c..ec3018b657 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -56,8 +56,6 @@ public: // region in layer-stack space mutable Region dirtyRegion; // region in screen space - mutable Region swapRegion; - // region in screen space Region undefinedRegion; bool lastCompositionHadVisibleLayers; @@ -97,7 +95,7 @@ public: // Flip the front and back buffers if the back buffer is "dirty". Might // be instantaneous, might involve copying the frame buffer around. - void flip(const Region& dirty) const; + void flip() const; int getWidth() const; int getHeight() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c142f2ff49..142892e874 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1534,7 +1534,7 @@ void SurfaceFlinger::doDebugFlashRegions() const Region dirtyRegion(hw->getDirtyRegion(repaintEverything)); if (!dirtyRegion.isEmpty()) { // redraw the whole screen - doComposeSurfaces(hw, Region(hw->bounds())); + doComposeSurfaces(hw); // and draw the dirty region const int32_t height = hw->getHeight(); @@ -2009,8 +2009,7 @@ void SurfaceFlinger::doComposition() { doDisplayComposition(hw, dirtyRegion); hw->dirtyRegion.clear(); - hw->flip(hw->swapRegion); - hw->swapRegion.clear(); + hw->flip(); } } postFramebuffer(); @@ -2643,30 +2642,17 @@ void SurfaceFlinger::doDisplayComposition( } ALOGV("doDisplayComposition"); - - Region dirtyRegion(inDirtyRegion); - - // compute the invalid region - displayDevice->swapRegion.orSelf(dirtyRegion); - - // we need to redraw everything (the whole screen) - dirtyRegion.set(displayDevice->bounds()); - displayDevice->swapRegion = dirtyRegion; - - if (!doComposeSurfaces(displayDevice, dirtyRegion)) return; - - // update the swap region and clear the dirty region - displayDevice->swapRegion.orSelf(dirtyRegion); + if (!doComposeSurfaces(displayDevice)) return; // swap buffers (presentation) displayDevice->swapBuffers(getHwComposer()); } -bool SurfaceFlinger::doComposeSurfaces( - const sp& displayDevice, const Region& dirty) +bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice) { ALOGV("doComposeSurfaces"); + const Region bounds(displayDevice->bounds()); const DisplayRenderArea renderArea(displayDevice); const auto hwcId = displayDevice->getHwcDisplayId(); @@ -2708,10 +2694,7 @@ bool SurfaceFlinger::doComposeSurfaces( // We'll revisit later if needed. mRenderEngine->clearWithColor(0, 0, 0, 0); } else { - // we start with the whole screen area - const Region bounds(displayDevice->getBounds()); - - // we remove the scissor part + // we start with the whole screen area and remove the scissor part // we're left with the letterbox region // (common case is that letterbox ends-up being empty) const Region letterbox(bounds.subtract(displayDevice->getScissor())); @@ -2719,9 +2702,6 @@ bool SurfaceFlinger::doComposeSurfaces( // compute the area to clear Region region(displayDevice->undefinedRegion.merge(letterbox)); - // but limit it to the dirty region - region.andSelf(dirty); - // screen is already cleared here if (!region.isEmpty()) { // can happen with SurfaceView @@ -2758,7 +2738,7 @@ bool SurfaceFlinger::doComposeSurfaces( // we're using h/w composer bool firstLayer = true; for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - const Region clip(dirty.intersect( + const Region clip(bounds.intersect( displayTransform.transform(layer->visibleRegion))); ALOGV("Layer: %s", layer->getName().string()); ALOGV(" Composition type: %s", @@ -2794,7 +2774,7 @@ bool SurfaceFlinger::doComposeSurfaces( } else { // we're not using h/w composer for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - const Region clip(dirty.intersect( + const Region clip(bounds.intersect( displayTransform.transform(layer->visibleRegion))); if (!clip.isEmpty()) { layer->draw(renderArea, clip); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 58d999865e..974de94930 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -543,7 +543,7 @@ private: // compose surfaces for display hw. this fails if using GL and the surface // has been destroyed and is no longer valid. - bool doComposeSurfaces(const sp& displayDevice, const Region& dirty); + bool doComposeSurfaces(const sp& displayDevice); void postFramebuffer(); void drawWormhole(const sp& displayDevice, const Region& region) const; -- cgit v1.2.3-59-g8ed1b From 40482ff650751819d4104c10a30974838168438c Mon Sep 17 00:00:00 2001 From: Chavi Weingarten Date: Thu, 30 Nov 2017 01:51:40 +0000 Subject: Revert "Revert "Use GraphicBuffer instead of GBP for screenshots."" This reverts commit 707b8f3507fa4a3915844c7a4730e67f94eee2f7. Reason for revert: Ready to test out changes with SystemUI update Change-Id: I9fd0cb7ad9cc68d2366fc5ec4ab087fbe4c21f3b --- libs/gui/ISurfaceComposer.cpp | 71 ++++--- libs/gui/Surface.cpp | 21 ++ libs/gui/SurfaceComposerClient.cpp | 174 +--------------- libs/gui/include/gui/ISurfaceComposer.h | 15 +- libs/gui/include/gui/Surface.h | 2 + libs/gui/include/gui/SurfaceComposerClient.h | 72 +------ libs/gui/tests/Surface_test.cpp | 13 +- services/surfaceflinger/SurfaceFlinger.cpp | 112 +++------- services/surfaceflinger/SurfaceFlinger.h | 18 +- services/surfaceflinger/tests/Transaction_test.cpp | 229 +++++++++------------ 10 files changed, 227 insertions(+), 500 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index c21c5e3eb8..5de84ecbab 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -100,17 +100,13 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - ISurfaceComposer::Rotation rotation) - { + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); @@ -118,21 +114,45 @@ public: data.writeInt32(maxLayerZ); data.writeInt32(static_cast(useIdentityTransform)); data.writeInt32(static_cast(rotation)); - remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); - return reply.readInt32(); + status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); + + if (err != NO_ERROR) { + return err; + } + + err = reply.readInt32(); + if (err != NO_ERROR) { + return err; + } + + *outBuffer = new GraphicBuffer(); + reply.read(**outBuffer); + return err; } virtual status_t captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale) { + sp* outBuffer, const Rect& sourceCrop, + float frameScale) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); - data.writeStrongBinder(IInterface::asBinder(producer)); data.write(sourceCrop); data.writeFloat(frameScale); - remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); - return reply.readInt32(); + status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); + + if (err != NO_ERROR) { + return err; + } + + err = reply.readInt32(); + if (err != NO_ERROR) { + return err; + } + + *outBuffer = new GraphicBuffer(); + reply.read(**outBuffer); + + return err; } virtual bool authenticateSurfaceTexture( @@ -583,8 +603,7 @@ status_t BnSurfaceComposer::onTransact( case CAPTURE_SCREEN: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); - sp producer = - interface_cast(data.readStrongBinder()); + sp outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); uint32_t reqWidth = data.readUint32(); @@ -594,24 +613,28 @@ status_t BnSurfaceComposer::onTransact( bool useIdentityTransform = static_cast(data.readInt32()); int32_t rotation = data.readInt32(); - status_t res = captureScreen(display, producer, - sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, - useIdentityTransform, - static_cast(rotation)); + status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight, + minLayerZ, maxLayerZ, useIdentityTransform, + static_cast(rotation)); reply->writeInt32(res); + if (res == NO_ERROR) { + reply->write(*outBuffer); + } return NO_ERROR; } case CAPTURE_LAYERS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp layerHandleBinder = data.readStrongBinder(); - sp producer = - interface_cast(data.readStrongBinder()); + sp outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); float frameScale = data.readFloat(); - status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale); + status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale); reply->writeInt32(res); + if (res == NO_ERROR) { + reply->write(*outBuffer); + } return NO_ERROR; } case AUTHENTICATE_SURFACE: { diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e9393831c7..80216bc63e 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1760,4 +1760,25 @@ status_t Surface::getAndFlushRemovedBuffers(std::vector>* out) return OK; } +status_t Surface::attachAndQueueBuffer(Surface* surface, sp buffer) { + if (buffer == nullptr) { + return BAD_VALUE; + } + int err = static_cast(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT, + NATIVE_WINDOW_API_CPU); + if (err != OK) { + return err; + } + err = surface->attachBuffer(buffer->getNativeBuffer()); + if (err != OK) { + return err; + } + err = static_cast(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1); + if (err != OK) { + return err; + } + err = surface->disconnect(NATIVE_WINDOW_API_CPU); + return err; +} + }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2466d2555a..0dbe786f1a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -717,181 +717,27 @@ status_t SurfaceComposerClient::getHdrCapabilities(const sp& display, // ---------------------------------------------------------------------------- -status_t ScreenshotClient::capture( - const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) { +status_t ScreenshotClient::capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation, + sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureScreen(display, producer, sourceCrop, - reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform); -} - -status_t ScreenshotClient::captureToBuffer(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, - uint32_t rotation, - sp* outBuffer) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - - sp gbpConsumer; - sp producer; - BufferQueue::createBufferQueue(&producer, &gbpConsumer); - sp consumer(new BufferItemConsumer(gbpConsumer, - GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER, - 1, true)); - - status_t ret = s->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, - static_cast(rotation)); + status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ, + maxLayerZ, useIdentityTransform, + static_cast(rotation)); if (ret != NO_ERROR) { return ret; } - BufferItem b; - consumer->acquireBuffer(&b, 0, true); - *outBuffer = b.mGraphicBuffer; return ret; } -status_t ScreenshotClient::captureLayers(const sp& layerHandle, - const sp& producer, - Rect sourceCrop, float frameScale) { +status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureLayers(layerHandle, producer, sourceCrop, frameScale); -} - -status_t ScreenshotClient::captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, - float frameScale, sp* outBuffer) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - - sp gbpConsumer; - sp producer; - BufferQueue::createBufferQueue(&producer, &gbpConsumer); - sp consumer(new BufferItemConsumer(gbpConsumer, - GRALLOC_USAGE_HW_TEXTURE | - GRALLOC_USAGE_SW_READ_NEVER | - GRALLOC_USAGE_SW_WRITE_NEVER, - 1, true)); - - status_t ret = s->captureLayers(layerHandle, producer, sourceCrop, frameScale); - if (ret != NO_ERROR) { - return ret; - } - BufferItem b; - consumer->acquireBuffer(&b, 0, true); - *outBuffer = b.mGraphicBuffer; + status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale); return ret; } - -ScreenshotClient::ScreenshotClient() - : mHaveBuffer(false) { - memset(&mBuffer, 0, sizeof(mBuffer)); -} - -ScreenshotClient::~ScreenshotClient() { - ScreenshotClient::release(); -} - -sp ScreenshotClient::getCpuConsumer() const { - if (mCpuConsumer == NULL) { - sp consumer; - BufferQueue::createBufferQueue(&mProducer, &consumer); - mCpuConsumer = new CpuConsumer(consumer, 1); - mCpuConsumer->setName(String8("ScreenshotClient")); - } - return mCpuConsumer; -} - -status_t ScreenshotClient::update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation) { - sp s(ComposerService::getComposerService()); - if (s == NULL) return NO_INIT; - sp cpuConsumer = getCpuConsumer(); - - if (mHaveBuffer) { - mCpuConsumer->unlockBuffer(mBuffer); - memset(&mBuffer, 0, sizeof(mBuffer)); - mHaveBuffer = false; - } - - status_t err = s->captureScreen(display, mProducer, sourceCrop, - reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform, - static_cast(rotation)); - - if (err == NO_ERROR) { - err = mCpuConsumer->lockNextBuffer(&mBuffer); - if (err == NO_ERROR) { - mHaveBuffer = true; - } - } - return err; -} - -status_t ScreenshotClient::update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform) { - - return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, - minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, - bool useIdentityTransform) { - return ScreenshotClient::update(display, sourceCrop, 0, 0, - INT32_MIN, INT32_MAX, - useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -status_t ScreenshotClient::update(const sp& display, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) { - return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, - INT32_MIN, INT32_MAX, - useIdentityTransform, ISurfaceComposer::eRotateNone); -} - -void ScreenshotClient::release() { - if (mHaveBuffer) { - mCpuConsumer->unlockBuffer(mBuffer); - memset(&mBuffer, 0, sizeof(mBuffer)); - mHaveBuffer = false; - } - mCpuConsumer.clear(); -} - -void const* ScreenshotClient::getPixels() const { - return mBuffer.data; -} - -uint32_t ScreenshotClient::getWidth() const { - return mBuffer.width; -} - -uint32_t ScreenshotClient::getHeight() const { - return mBuffer.height; -} - -PixelFormat ScreenshotClient::getFormat() const { - return mBuffer.format; -} - -uint32_t ScreenshotClient::getStride() const { - return mBuffer.stride; -} - -size_t ScreenshotClient::getSize() const { - return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format); -} - -android_dataspace ScreenshotClient::getDataSpace() const { - return mBuffer.dataSpace; -} - // ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 1e4c329e1e..e26e332589 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -29,6 +29,7 @@ #include #include +#include #include @@ -167,16 +168,14 @@ public: /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. */ - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - Rotation rotation = eRotateNone) = 0; + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + Rotation rotation = eRotateNone) = 0; virtual status_t captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale = 1.0) = 0; + sp* outBuffer, const Rect& sourceCrop, + float frameScale = 1.0) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 3fe29d955b..354f23ab06 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -283,6 +283,8 @@ public: android_dataspace_t getBuffersDataSpace(); + static status_t attachAndQueueBuffer(Surface* surface, sp buffer); + protected: enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index b0fa922cd9..3f13946339 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -279,74 +279,16 @@ private: // --------------------------------------------------------------------------- -class ScreenshotClient -{ +class ScreenshotClient { public: // if cropping isn't required, callers may pass in a default Rect, e.g.: // capture(display, producer, Rect(), reqWidth, ...); - static status_t capture( - const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform); - static status_t captureToBuffer( - const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, - uint32_t rotation, - sp* outbuffer); - - static status_t captureLayers(const sp& layerHandle, - const sp& producer, Rect sourceCrop, - float frameScale); - static status_t captureLayersToBuffer(const sp& layerHandle, Rect sourceCrop, - float frameScale, sp* outBuffer); - -private: - mutable sp mCpuConsumer; - mutable sp mProducer; - CpuConsumer::LockedBuffer mBuffer; - bool mHaveBuffer; - -public: - ScreenshotClient(); - ~ScreenshotClient(); - - // frees the previous screenshot and captures a new one - // if cropping isn't required, callers may pass in a default Rect, e.g.: - // update(display, Rect(), useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform); - status_t update(const sp& display, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, uint32_t rotation); - - sp getCpuConsumer() const; - - // release memory occupied by the screenshot - void release(); - - // pixels are valid until this object is freed or - // release() or update() is called - void const* getPixels() const; - - uint32_t getWidth() const; - uint32_t getHeight() const; - PixelFormat getFormat() const; - uint32_t getStride() const; - // size of allocated memory in bytes - size_t getSize() const; - android_dataspace getDataSpace() const; + static status_t capture(const sp& display, Rect sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, uint32_t rotation, + sp* outBuffer); + static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float fameScale, + sp* outBuffer); }; // --------------------------------------------------------------------------- diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index ac4eb0cb1d..470a338639 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -116,14 +116,11 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { sp anw(mSurface); // Verify the screenshot works with no protected buffers. - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay( ISurfaceComposer::eDisplayIdMain)); - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), + sp outBuffer; + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), 64, 64, 0, 0x7fffffff, false)); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), @@ -154,7 +151,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { &buf)); ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } - ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), + ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(), 64, 64, 0, 0x7fffffff, false)); } @@ -524,13 +521,13 @@ public: status_t setActiveColorMode(const sp& /*display*/, android_color_mode_t /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp& /*display*/, - const sp& /*producer*/, + sp* /*outBuffer*/, Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/, bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, - const sp& /*producer*/, + sp* /*outBuffer*/, const Rect& /*sourceCrop*/, float /*frameScale*/) override { return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d81178c559..4acd448293 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4339,44 +4339,10 @@ private: const int mApi; }; -static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth, - uint32_t requestedHeight, bool hasWideColorDisplay, - bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) { - const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - - int err = 0; - err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight); - err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); - err |= native_window_set_usage(window, usage); - - if (hasWideColorDisplay) { - err |= native_window_set_buffers_data_space(window, - renderEngineUsesWideColor - ? HAL_DATASPACE_DISPLAY_P3 - : HAL_DATASPACE_V0_SRGB); - } - - if (err != NO_ERROR) { - return BAD_VALUE; - } - - /* TODO: Once we have the sync framework everywhere this can use - * server-side waits on the fence that dequeueBuffer returns. - */ - err = native_window_dequeue_buffer_and_wait(window, outBuffer); - if (err != NO_ERROR) { - return err; - } - - return NO_ERROR; -} - -status_t SurfaceFlinger::captureScreen(const sp& display, - const sp& producer, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ, - int32_t maxLayerZ, bool useIdentityTransform, +status_t SurfaceFlinger::captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, + bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { ATRACE_CALL(); @@ -4387,18 +4353,18 @@ status_t SurfaceFlinger::captureScreen(const sp& display, auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, device, minLayerZ, maxLayerZ, std::placeholders::_1); - return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform); + return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform); } status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, - const sp& producer, - const Rect& sourceCrop, float frameScale) { + sp* outBuffer, const Rect& sourceCrop, + float frameScale) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: LayerRenderArea(const sp& layer, const Rect crop, int32_t reqWidth, - int32_t reqHeight) + int32_t reqHeight) : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} const Transform& getTransform() const override { // Make the top level transform the inverse the transform and it's parent so it sets @@ -4461,51 +4427,21 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, visitor(layer); }); }; - return captureScreenCommon(renderArea, traverseLayers, producer, false); + return captureScreenCommon(renderArea, traverseLayers, outBuffer, false); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const sp& producer, + sp* outBuffer, bool useIdentityTransform) { ATRACE_CALL(); - if (CC_UNLIKELY(producer == 0)) - return BAD_VALUE; - renderArea.updateDimensions(); - // if we have secure windows on this display, never allow the screen capture - // unless the producer interface is local (i.e.: we can take a screenshot for - // ourselves). - bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder(); - - // create a surface (because we're a producer, and we need to - // dequeue/queue a buffer) - sp surface = new Surface(producer, false); - - // Put the screenshot Surface into async mode so that - // Layer::headFenceHasSignaled will always return true and we'll latch the - // first buffer regardless of whether or not its acquire fence has - // signaled. This is needed to avoid a race condition in the rotation - // animation. See b/30209608 - surface->setAsyncMode(true); - - ANativeWindow* window = surface.get(); - - status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); - if (result != NO_ERROR) { - return result; - } - WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL); - - ANativeWindowBuffer* buffer = nullptr; - result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(), - hasWideColorDisplay && !mForceNativeColorMode, - getRenderEngine().usesWideColor(), &buffer); - if (result != NO_ERROR) { - return result; - } + const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; + *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(), + HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot"); // This mutex protects syncFd and captureResult for communication of the return values from the // main thread back to this Binder thread @@ -4530,8 +4466,8 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, int fd = -1; { Mutex::Autolock _l(mStateLock); - result = captureScreenImplLocked(renderArea, traverseLayers, buffer, - useIdentityTransform, isLocalScreenshot, &fd); + result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), + useIdentityTransform, &fd); } { @@ -4542,7 +4478,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } }); - result = postMessageAsync(message); + status_t result = postMessageAsync(message); if (result == NO_ERROR) { captureCondition.wait(captureLock, [&]() { return captureResult; }); while (*captureResult == EAGAIN) { @@ -4557,9 +4493,10 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, } if (result == NO_ERROR) { - // queueBuffer takes ownership of syncFd - result = window->queueBuffer(window, buffer, syncFd); + sync_wait(syncFd, -1); + close(syncFd); } + return result; } @@ -4602,7 +4539,8 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, } engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode); - engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode()); + engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE + : renderArea.getActiveColorMode()); // make sure to clear all GL error flags engine.checkErrors(); @@ -4645,7 +4583,7 @@ private: status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, - bool useIdentityTransform, bool isLocalScreenshot, + bool useIdentityTransform, int* outSyncFd) { ATRACE_CALL(); @@ -4655,7 +4593,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure()); }); - if (!isLocalScreenshot && secureLayerIsVisible) { + if (secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); return PERMISSION_DENIED; } @@ -4804,4 +4742,4 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" -#endif +#endif \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f61dc756c2..a01d353a70 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -291,13 +291,11 @@ private: std::vector* outSupported) const; virtual sp createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp); - virtual status_t captureScreen(const sp& display, - const sp& producer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - int32_t minLayerZ, int32_t maxLayerZ, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation); - virtual status_t captureLayers(const sp& parentHandle, - const sp& producer, + virtual status_t captureScreen(const sp& display, sp* outBuffer, + Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, + ISurfaceComposer::Rotation rotation); + virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, const Rect& sourceCrop, float frameScale); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); @@ -436,15 +434,13 @@ private: void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, bool yswap, bool useIdentityTransform); - status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const sp& producer, + sp* outBuffer, bool useIdentityTransform); - status_t captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, - bool isLocalScreenshot, int* outSyncFd); + int* outSyncFd); void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 39aef8164c..ff81dc9461 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -104,20 +104,22 @@ void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const } // Check if a region has the specified color. -void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect, +void expectBufferColor(const sp& outBuffer, uint8_t* pixels, const Rect& rect, const Color& color, uint8_t tolerance) { int32_t x = rect.left; int32_t y = rect.top; int32_t width = rect.right - rect.left; int32_t height = rect.bottom - rect.top; - if (x + width > int32_t(buffer.width)) { - x = std::min(x, int32_t(buffer.width)); - width = buffer.width - x; + int32_t bufferWidth = int32_t(outBuffer->getWidth()); + int32_t bufferHeight = int32_t(outBuffer->getHeight()); + if (x + width > bufferWidth) { + x = std::min(x, bufferWidth); + width = bufferWidth - x; } - if (y + height > int32_t(buffer.height)) { - y = std::min(y, int32_t(buffer.height)); - height = buffer.height - y; + if (y + height > bufferHeight) { + y = std::min(y, bufferHeight); + height = bufferHeight - y; } auto colorCompare = [tolerance](uint8_t a, uint8_t b) { @@ -125,8 +127,7 @@ void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect return tmp <= tolerance; }; for (int32_t j = 0; j < height; j++) { - const uint8_t* src = - static_cast(buffer.data) + (buffer.stride * (y + j) + x) * 4; + const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) @@ -170,30 +171,38 @@ class ScreenCapture : public RefBase { public: static void captureScreen(sp* sc, int32_t minLayerZ = 0, int32_t maxLayerZ = std::numeric_limits::max()) { - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); sp sf(ComposerService::getComposerService()); sp display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); SurfaceComposerClient::Transaction().apply(true); + sp outBuffer; ASSERT_EQ(NO_ERROR, - sf->captureScreen(display, producer, Rect(), 0, 0, minLayerZ, maxLayerZ, false)); - *sc = new ScreenCapture(cpuConsumer); + sf->captureScreen(display, &outBuffer, Rect(), 0, 0, minLayerZ, maxLayerZ, + false)); + *sc = new ScreenCapture(outBuffer); + } + + static void captureLayers(std::unique_ptr* sc, sp& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { + sp sf(ComposerService::getComposerService()); + SurfaceComposerClient::Transaction().apply(true); + + sp outBuffer; + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale)); + *sc = std::make_unique(outBuffer); } void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); - expectBufferColor(mBuf, rect, color, tolerance); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); + expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance); } void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); const bool leftBorder = rect.left > 0; const bool topBorder = rect.top > 0; - const bool rightBorder = rect.right < int32_t(mBuf.width); - const bool bottomBorder = rect.bottom < int32_t(mBuf.height); + const bool rightBorder = rect.right < int32_t(mOutBuffer->getWidth()); + const bool bottomBorder = rect.bottom < int32_t(mOutBuffer->getHeight()); if (topBorder) { Rect top(rect.left, rect.top - 1, rect.right, rect.top); @@ -246,9 +255,8 @@ public: } void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format); - const uint8_t* img = static_cast(mBuf.data); - const uint8_t* pixel = img + (4 * (y * mBuf.stride + x)); + ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); + const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x)); if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { String8 err(String8::format("pixel @ (%3d, %3d): " "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", @@ -263,58 +271,15 @@ public: void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } -private: - ScreenCapture(const sp& cc) : mCC(cc) { - EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf)); + ScreenCapture(const sp& outBuffer) : mOutBuffer(outBuffer) { + mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast(&mPixels)); } - ~ScreenCapture() { mCC->unlockBuffer(mBuf); } - - sp mCC; - CpuConsumer::LockedBuffer mBuf; -}; - -class CaptureLayer { -public: - static void captureScreen(std::unique_ptr* sc, sp& parentHandle, - Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - sp sf(ComposerService::getComposerService()); - SurfaceComposerClient::Transaction().apply(true); - ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale)); - *sc = std::make_unique(cpuConsumer); - } - - void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { - ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuffer.format); - const uint8_t* img = static_cast(mBuffer.data); - const uint8_t* pixel = img + (4 * (y * mBuffer.stride + x)); - if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { - String8 err(String8::format("pixel @ (%3d, %3d): " - "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", - x, y, r, g, b, pixel[0], pixel[1], pixel[2])); - EXPECT_EQ(String8(), err) << err.string(); - } - } - - void expectFGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 195, 63, 63); } - - void expectBGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 63, 63, 195); } - - void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } - - CaptureLayer(const sp& cc) : mCC(cc) { - EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuffer)); - } - - ~CaptureLayer() { mCC->unlockBuffer(mBuffer); } + ~ScreenCapture() { mOutBuffer->unlock(); } private: - sp mCC; - CpuConsumer::LockedBuffer mBuffer; + sp mOutBuffer; + uint8_t* mPixels = NULL; }; class LayerTransactionTest : public ::testing::Test { @@ -858,21 +823,17 @@ TEST_F(LayerTransactionTest, SetFlagsSecure) { ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED)); sp composer = ComposerService::getComposerService(); - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - + sp outBuffer; Transaction() .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) .apply(true); ASSERT_EQ(PERMISSION_DENIED, - composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); ASSERT_EQ(NO_ERROR, - composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase, + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase, false)); } @@ -1504,7 +1465,7 @@ TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) { } } -class LayerUpdateTest : public ::testing::Test { +class LayerUpdateTest : public LayerTransactionTest { protected: virtual void SetUp() { mComposerClient = new SurfaceComposerClient; @@ -2318,12 +2279,12 @@ TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { class ScreenCaptureTest : public LayerUpdateTest { protected: - std::unique_ptr mCapture; + std::unique_ptr mCapture; }; TEST_F(ScreenCaptureTest, CaptureSingleLayer) { auto bgHandle = mBGSurfaceControl->getHandle(); - CaptureLayer::captureScreen(&mCapture, bgHandle); + ScreenCapture::captureLayers(&mCapture, bgHandle); mCapture->expectBGColor(0, 0); // Doesn't capture FG layer which is at 64, 64 mCapture->expectBGColor(64, 64); @@ -2340,7 +2301,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { SurfaceComposerClient::Transaction().show(child).apply(true); // Captures mFGSurfaceControl layer and its child. - CaptureLayer::captureScreen(&mCapture, fgHandle); + ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); } @@ -2365,7 +2326,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { .apply(true); // Captures mFGSurfaceControl, its child, and the grandchild. - CaptureLayer::captureScreen(&mCapture, fgHandle); + ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); mCapture->checkPixel(5, 5, 50, 50, 50); @@ -2381,7 +2342,7 @@ TEST_F(ScreenCaptureTest, CaptureChildOnly) { SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true); // Captures only the child layer, and not the parent. - CaptureLayer::captureScreen(&mCapture, childHandle); + ScreenCapture::captureLayers(&mCapture, childHandle); mCapture->expectChildColor(0, 0); mCapture->expectChildColor(9, 9); } @@ -2407,94 +2368,96 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { auto grandchildHandle = grandchild->getHandle(); // Captures only the grandchild. - CaptureLayer::captureScreen(&mCapture, grandchildHandle); + ScreenCapture::captureLayers(&mCapture, grandchildHandle); mCapture->checkPixel(0, 0, 50, 50, 50); mCapture->checkPixel(4, 4, 50, 50, 50); } TEST_F(ScreenCaptureTest, CaptureCrop) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = mComposerClient->createSurface( - String8("Blue surface"), - 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = + mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, + 0, redLayer.get()); - fillSurfaceRGBA8(redLayer, 255, 0, 0); - fillSurfaceRGBA8(blueLayer, 0, 0, 255); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX-1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX - 1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - CaptureLayer::captureScreen(&mCapture, redLayerHandle); - mCapture->checkPixel(29, 29, 0, 0, 255); - mCapture->checkPixel(30, 30, 255, 0, 0); + ScreenCapture::captureLayers(&mCapture, redLayerHandle); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); Rect crop = Rect(0, 0, 30, 30); - CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop); + ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop); // Capturing the cropped screen, cropping out the shown red area, should leave only the blue // area visible. - mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureSize) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); - sp blueLayer = mComposerClient->createSurface( - String8("Blue surface"), - 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); + sp blueLayer = + mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, + 0, redLayer.get()); - fillSurfaceRGBA8(redLayer, 255, 0, 0); - fillSurfaceRGBA8(blueLayer, 0, 0, 255); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE)); SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX-1) - .show(redLayer) - .show(blueLayer) - .apply(true); + .setLayer(redLayer, INT32_MAX - 1) + .show(redLayer) + .show(blueLayer) + .apply(true); auto redLayerHandle = redLayer->getHandle(); // Capturing full screen should have both red and blue are visible. - CaptureLayer::captureScreen(&mCapture, redLayerHandle); - mCapture->checkPixel(29, 29, 0, 0, 255); - mCapture->checkPixel(30, 30, 255, 0, 0); - - CaptureLayer::captureScreen(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); + ScreenCapture::captureLayers(&mCapture, redLayerHandle); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); + + ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. - mCapture->checkPixel(14, 14, 0, 0, 255); - mCapture->checkPixel(15, 15, 255, 0, 0); - mCapture->checkPixel(29, 29, 255, 0, 0); + mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED); mCapture->checkPixel(30, 30, 0, 0, 0); } TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { - sp redLayer = mComposerClient->createSurface( - String8("Red surface"), - 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60, + PIXEL_FORMAT_RGBA_8888, 0); - fillSurfaceRGBA8(redLayer, 255, 0, 0); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED)); auto redLayerHandle = redLayer->getHandle(); mComposerClient->destroySurface(redLayerHandle); SurfaceComposerClient::Transaction().apply(true); - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - sp cpuConsumer = new CpuConsumer(consumer, 1); - sp sf(ComposerService::getComposerService()); + sp outBuffer; // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND - ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0)); + sp sf(ComposerService::getComposerService()); + ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); } -} \ No newline at end of file +} // namespace android -- cgit v1.2.3-59-g8ed1b From 105b7dcf6b2e3e4af368cabeec275008b7e73806 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Sat, 4 Nov 2017 20:28:14 -0700 Subject: surfaceflinger: Create SurfaceFlingerBE class Split SurfaceFlinger object into a backend and frontend version. This change creates the backend struct and only puts a single data item in that struct. Follow-on changes to move more things to the backend will follow Test: build Change-Id: I0fd6b4eb506791346da2b9f94cc12d9cf854ad08 --- services/surfaceflinger/SurfaceFlinger.cpp | 106 +++++++++++++++-------------- services/surfaceflinger/SurfaceFlinger.h | 67 ++++++++++-------- 2 files changed, 95 insertions(+), 78 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 142892e874..db6cb2bd90 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -119,6 +119,10 @@ private: }; } // namespace anonymous +SurfaceFlingerBE::SurfaceFlingerBE() + : mComposerSequenceId(0) { +} + // --------------------------------------------------------------------------- const String16 sHardwareTest("android.permission.HARDWARE_TEST"); @@ -189,8 +193,7 @@ SurfaceFlinger::SurfaceFlinger() mLastSwapTime(0), mNumLayers(0), mVrFlingerRequestsDisplay(false), - mMainThreadId(std::this_thread::get_id()), - mComposerSequenceId(0) + mMainThreadId(std::this_thread::get_id()) { ALOGI("SurfaceFlinger is starting"); @@ -613,8 +616,8 @@ void SurfaceFlinger::init() { LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, "Starting with vr flinger active is not currently supported."); - mHwc.reset(new HWComposer(mHwcServiceName)); - mHwc->registerCallback(this, mComposerSequenceId); + getBE().mHwc.reset(new HWComposer(mHwcServiceName)); + getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId); if (useVrFlinger) { auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) { @@ -631,8 +634,8 @@ void SurfaceFlinger::init() { }); postMessageAsync(message); }; - mVrFlinger = dvr::VrFlinger::Create(mHwc->getComposer(), - mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0), + mVrFlinger = dvr::VrFlinger::Create(getBE().mHwc->getComposer(), + getBE().mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0), vrFlingerRequestDisplayCallback); if (!mVrFlinger) { ALOGE("Failed to start vrflinger"); @@ -1042,7 +1045,7 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp& display, } std::unique_ptr capabilities = - mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId()); + getBE().mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId()); if (capabilities) { std::swap(*outCapabilities, *capabilities); } else { @@ -1190,7 +1193,7 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) { return; } - const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); + const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); const nsecs_t period = activeConfig->getVsyncPeriod(); mPrimaryDispSync.reset(); @@ -1233,12 +1236,12 @@ void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t displayId, int64_t timestamp) { Mutex::Autolock lock(mStateLock); // Ignore any vsyncs from a previous hardware composer. - if (sequenceId != mComposerSequenceId) { + if (sequenceId != getBE().mComposerSequenceId) { return; } int32_t type; - if (!mHwc->onVsync(displayId, timestamp, &type)) { + if (!getBE().mHwc->onVsync(displayId, timestamp, &type)) { return; } @@ -1274,7 +1277,7 @@ void SurfaceFlinger::createDefaultDisplayDevice() { sp consumer; BufferQueue::createBufferQueue(&producer, &consumer); - sp fbs = new FramebufferSurface(*mHwc, type, consumer); + sp fbs = new FramebufferSurface(*getBE().mHwc, type, consumer); bool hasWideColorModes = false; std::vector modes = getHwComposer().getColorModes(type); @@ -1326,20 +1329,20 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, std::this_thread::get_id() != mMainThreadId); if (primaryDisplay) { - mHwc->onHotplug(display, connection); + getBE().mHwc->onHotplug(display, connection); if (!mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY].get()) { createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY); } createDefaultDisplayDevice(); } else { - if (sequenceId != mComposerSequenceId) { + if (sequenceId != getBE().mComposerSequenceId) { return; } - if (mHwc->isUsingVrComposer()) { + if (getBE().mHwc->isUsingVrComposer()) { ALOGE("External displays are not supported by the vr hardware composer."); return; } - mHwc->onHotplug(display, connection); + getBE().mHwc->onHotplug(display, connection); auto type = DisplayDevice::DISPLAY_EXTERNAL; if (connection == HWC2::Connection::Connected) { createBuiltinDisplayLocked(type); @@ -1356,7 +1359,7 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*display*/) { Mutex::Autolock lock(mStateLock); - if (sequenceId != mComposerSequenceId) { + if (sequenceId != getBE().mComposerSequenceId) { return; } repaintEverythingLocked(); @@ -1385,11 +1388,11 @@ void SurfaceFlinger::updateVrFlinger() { if (!mVrFlinger) return; bool vrFlingerRequestsDisplay = mVrFlingerRequestsDisplay; - if (vrFlingerRequestsDisplay == mHwc->isUsingVrComposer()) { + if (vrFlingerRequestsDisplay == getBE().mHwc->isUsingVrComposer()) { return; } - if (vrFlingerRequestsDisplay && !mHwc->getComposer()->isRemote()) { + if (vrFlingerRequestsDisplay && !getBE().mHwc->getComposer()->isRemote()) { ALOGE("Vr flinger is only supported for remote hardware composer" " service connections. Ignoring request to transition to vr" " flinger."); @@ -1407,13 +1410,12 @@ void SurfaceFlinger::updateVrFlinger() { } resetDisplayState(); - mHwc.reset(); // Delete the current instance before creating the new one - mHwc.reset(new HWComposer( - vrFlingerRequestsDisplay ? "vr" : mHwcServiceName)); - mHwc->registerCallback(this, ++mComposerSequenceId); + getBE().mHwc.reset(); // Delete the current instance before creating the new one + getBE().mHwc.reset(new HWComposer(vrFlingerRequestsDisplay ? "vr" : mHwcServiceName)); + getBE().mHwc->registerCallback(this, ++getBE().mComposerSequenceId); - LOG_ALWAYS_FATAL_IF(!mHwc->getComposer()->isRemote(), - "Switched to non-remote hardware composer"); + LOG_ALWAYS_FATAL_IF(!getBE().mHwc->getComposer()->isRemote(), + "Switched to non-remote hardware composer"); if (vrFlingerRequestsDisplay) { mVrFlinger->GrantDisplayOwnership(); @@ -1430,7 +1432,7 @@ void SurfaceFlinger::updateVrFlinger() { 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 auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); const nsecs_t period = activeConfig->getVsyncPeriod(); mAnimFrameTracker.setDisplayRefreshPeriod(period); @@ -1508,13 +1510,13 @@ void SurfaceFlinger::handleMessageRefresh() { doComposition(); postComposition(refreshStartTime); - mPreviousPresentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); + mPreviousPresentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); mHadClientComposition = false; for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { const sp& displayDevice = mDisplays[displayId]; mHadClientComposition = mHadClientComposition || - mHwc->hasClientComposition(displayDevice->getHwcDisplayId()); + getBE().mHwc->hasClientComposition(displayDevice->getHwcDisplayId()); } mLayersWithQueuedFrames.clear(); @@ -1558,9 +1560,11 @@ void SurfaceFlinger::doDebugFlashRegions() continue; } - status_t result = displayDevice->prepareFrame(*mHwc); - ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:" - " %d (%s)", displayId, result, strerror(-result)); + status_t result = displayDevice->prepareFrame(*getBE().mHwc); + ALOGE_IF(result != NO_ERROR, + "prepareFrame for display %zd failed:" + " %d (%s)", + displayId, result, strerror(-result)); } } @@ -1664,7 +1668,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr glCompositionDoneFenceTime; - if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) { + if (getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) { glCompositionDoneFenceTime = std::make_shared(hw->getClientTargetAcquireFence()); mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime); @@ -1673,7 +1677,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } mDisplayTimeline.updateSignalTimes(); - sp presentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); + sp presentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); auto presentFenceTime = std::make_shared(presentFence); mDisplayTimeline.push(presentFenceTime); @@ -1724,7 +1728,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) // The HWC doesn't support present fences, so use the refresh // timestamp instead. nsecs_t presentTime = - mHwc->getRefreshTimestamp(HWC_DISPLAY_PRIMARY); + getBE().mHwc->getRefreshTimestamp(HWC_DISPLAY_PRIMARY); mAnimFrameTracker.setActualPresentTime(presentTime); } mAnimFrameTracker.advanceFrame(); @@ -1923,7 +1927,7 @@ void SurfaceFlinger::setUpHWComposer() { for (size_t i = 0; i < currentLayers.size(); i++) { const auto& layer = currentLayers[i]; if (!layer->hasHwcLayer(hwcId)) { - if (!layer->createHwcLayer(mHwc.get(), hwcId)) { + if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) { layer->forceClientComposition(hwcId); continue; } @@ -1950,7 +1954,7 @@ void SurfaceFlinger::setUpHWComposer() { continue; } if (colorMatrix != mPreviousColorMatrix) { - status_t result = mHwc->setColorTransform(hwcId, colorMatrix); + status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix); ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " "display %zd: %d", displayId, result); } @@ -1988,7 +1992,7 @@ void SurfaceFlinger::setUpHWComposer() { continue; } - status_t result = displayDevice->prepareFrame(*mHwc); + status_t result = displayDevice->prepareFrame(*getBE().mHwc); ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:" " %d (%s)", displayId, result, strerror(-result)); } @@ -2030,7 +2034,7 @@ void SurfaceFlinger::postFramebuffer() } const auto hwcId = displayDevice->getHwcDisplayId(); if (hwcId >= 0) { - mHwc->presentAndGetReleaseFences(hwcId); + getBE().mHwc->presentAndGetReleaseFences(hwcId); } displayDevice->onSwapBuffersCompleted(); displayDevice->makeCurrent(); @@ -2039,7 +2043,7 @@ void SurfaceFlinger::postFramebuffer() // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. auto hwcLayer = layer->getHwcLayer(hwcId); - sp releaseFence = mHwc->getLayerReleaseFence(hwcId, hwcLayer); + sp releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer); // If the layer was client composited in the previous frame, we // need to merge with the previous client target acquire fence. @@ -2058,14 +2062,14 @@ void SurfaceFlinger::postFramebuffer() // displayDevice->getVisibleLayersSortedByZ. The best we can do is to // supply them with the present fence. if (!displayDevice->getLayersNeedingFences().isEmpty()) { - sp presentFence = mHwc->getPresentFence(hwcId); + sp presentFence = getBE().mHwc->getPresentFence(hwcId); for (auto& layer : displayDevice->getLayersNeedingFences()) { layer->onLayerDisplayed(presentFence); } } if (hwcId >= 0) { - mHwc->clearReleaseFences(hwcId); + getBE().mHwc->clearReleaseFences(hwcId); } } @@ -2229,7 +2233,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (state.surface != NULL) { // Allow VR composer to use virtual displays. - if (mUseHwcVirtualDisplays || mHwc->isUsingVrComposer()) { + if (mUseHwcVirtualDisplays || getBE().mHwc->isUsingVrComposer()) { int width = 0; int status = state.surface->query( NATIVE_WINDOW_WIDTH, &width); @@ -2248,14 +2252,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) auto format = static_cast( intFormat); - mHwc->allocateVirtualDisplay(width, height, &format, + getBE().mHwc->allocateVirtualDisplay(width, height, &format, &hwcId); } // TODO: Plumb requested format back up to consumer sp vds = - new VirtualDisplaySurface(*mHwc, + new VirtualDisplaySurface(*getBE().mHwc, hwcId, state.surface, bqProducer, bqConsumer, state.displayName); @@ -2269,7 +2273,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) state.surface.get()); hwcId = state.type; - dispSurface = new FramebufferSurface(*mHwc, hwcId, bqConsumer); + dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer); producer = bqProducer; } @@ -2657,14 +2661,14 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev const auto hwcId = displayDevice->getHwcDisplayId(); mat4 oldColorMatrix; - const bool applyColorMatrix = !mHwc->hasDeviceComposition(hwcId) && - !mHwc->hasCapability(HWC2::Capability::SkipClientColorTransform); + const bool applyColorMatrix = !getBE().mHwc->hasDeviceComposition(hwcId) && + !getBE().mHwc->hasCapability(HWC2::Capability::SkipClientColorTransform); if (applyColorMatrix) { mat4 colorMatrix = mColorMatrix * mDaltonizer(); oldColorMatrix = getRenderEngine().setupColorTransform(colorMatrix); } - bool hasClientComposition = mHwc->hasClientComposition(hwcId); + bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId); if (hasClientComposition) { ALOGV("hasClientComposition"); @@ -2685,7 +2689,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev } // Never touch the framebuffer if we don't have any framebuffer layers - const bool hasDeviceComposition = mHwc->hasDeviceComposition(hwcId); + const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId); if (hasDeviceComposition) { // when using overlays, we assume a fully transparent framebuffer // NOTE: we could reduce how much we need to clear, for instance @@ -3359,7 +3363,7 @@ void SurfaceFlinger::onInitializeDisplays() { setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL, /*stateLockHeld*/ false); - const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); + const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); const nsecs_t period = activeConfig->getVsyncPeriod(); mAnimFrameTracker.setDisplayRefreshPeriod(period); @@ -3612,7 +3616,7 @@ void SurfaceFlinger::dumpStatsLocked(const Vector& args, size_t& index index++; } - const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); + const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); const nsecs_t period = activeConfig->getVsyncPeriod(); result.appendFormat("%" PRId64 "\n", period); @@ -3829,7 +3833,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, result.append(SyncFeatures::getInstance().toString()); result.append("\n"); - const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); + const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); colorizer.bold(result); result.append("DispSync configuration: "); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 974de94930..840c5e4d42 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -92,6 +92,7 @@ class RenderEngine; class EventControlThread; class VSyncSource; class InjectVSyncSource; +class SurfaceFlingerBE; typedef std::function TraverseLayersFunction; @@ -108,12 +109,48 @@ enum { eTransactionMask = 0x07 }; +class SurfaceFlingerBE +{ +public: + SurfaceFlingerBE(); + + // The current hardware composer interface. + // + // The following thread safety rules apply when accessing mHwc, either + // directly or via getHwComposer(): + // + // 1. When recreating mHwc, acquire mStateLock. We currently recreate mHwc + // only when switching into and out of vr. Recreating mHwc must only be + // done on the main thread. + // + // 2. When accessing mHwc on the main thread, it's not necessary to acquire + // mStateLock. + // + // 3. When accessing mHwc on a thread other than the main thread, we always + // need to acquire mStateLock. This is because the main thread could be + // in the process of destroying the current mHwc instance. + // + // The above thread safety rules only apply to SurfaceFlinger.cpp. In + // SurfaceFlinger_hwc1.cpp we create mHwc at surface flinger init and never + // destroy it, so it's always safe to access mHwc from any thread without + // acquiring mStateLock. + std::unique_ptr mHwc; + + // 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; +}; + + class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, private IBinder::DeathRecipient, private HWC2::ComposerCallback { public: + SurfaceFlingerBE& getBE() { return mBE; } + const SurfaceFlingerBE& getBE() const { return mBE; } // This is the phase offset in nanoseconds of the software vsync event // relative to the vsync event reported by HWComposer. The software vsync @@ -509,7 +546,7 @@ private: * H/W composer */ - HWComposer& getHwComposer() const { return *mHwc; } + HWComposer& getHwComposer() const { return *getBE().mHwc; } /* ------------------------------------------------------------------------ * Compositing @@ -632,28 +669,6 @@ private: // access must be protected by mInvalidateLock volatile int32_t mRepaintEverything; - // The current hardware composer interface. - // - // The following thread safety rules apply when accessing mHwc, either - // directly or via getHwComposer(): - // - // 1. When recreating mHwc, acquire mStateLock. We currently recreate mHwc - // only when switching into and out of vr. Recreating mHwc must only be - // done on the main thread. - // - // 2. When accessing mHwc on the main thread, it's not necessary to acquire - // mStateLock. - // - // 3. When accessing mHwc on a thread other than the main thread, we always - // need to acquire mStateLock. This is because the main thread could be - // in the process of destroying the current mHwc instance. - // - // The above thread safety rules only apply to SurfaceFlinger.cpp. In - // SurfaceFlinger_hwc1.cpp we create mHwc at surface flinger init and never - // destroy it, so it's always safe to access mHwc from any thread without - // acquiring mStateLock. - std::unique_ptr mHwc; - const std::string mHwcServiceName; // "default" for real use, something else for testing. // constant members (no synchronization needed for access) @@ -781,13 +796,11 @@ private: std::atomic 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; float mSaturation = 1.0f; bool mForceNativeColorMode = false; + + SurfaceFlingerBE mBE; }; }; // namespace android -- cgit v1.2.3-59-g8ed1b From bc8152863f81c9af1038d92c9eb8caca1cfd4027 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Sun, 5 Nov 2017 18:57:52 -0800 Subject: SF: RenderEngine/EGL state to SFBE Move RenderEngine and EGL handles to SurfaceFlingerBE Test: build Change-Id: Ifc6736882200db02df7a7a87eda6e909fa0f6ef2 --- services/surfaceflinger/SurfaceFlinger.cpp | 38 +++++++++++++++--------------- services/surfaceflinger/SurfaceFlinger.h | 12 ++++++---- 2 files changed, 27 insertions(+), 23 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index db6cb2bd90..b9afcc08ab 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -119,10 +119,6 @@ private: }; } // namespace anonymous -SurfaceFlingerBE::SurfaceFlingerBE() - : mComposerSequenceId(0) { -} - // --------------------------------------------------------------------------- const String16 sHardwareTest("android.permission.HARDWARE_TEST"); @@ -157,6 +153,12 @@ bool useTrebleTestingOverride() { return std::string(value) == "true"; } +SurfaceFlingerBE::SurfaceFlingerBE() + : mHwcServiceName(getHwcServiceName()), + mRenderEngine(nullptr), + mComposerSequenceId(0) { +} + SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), mTransactionFlags(0), @@ -165,8 +167,6 @@ SurfaceFlinger::SurfaceFlinger() mLayersRemoved(false), mLayersAdded(false), mRepaintEverything(0), - mHwcServiceName(getHwcServiceName()), - mRenderEngine(nullptr), mBootTime(systemTime()), mBuiltinDisplays(), mVisibleRegionsDirty(false), @@ -610,13 +610,13 @@ void SurfaceFlinger::init() { } // Get a RenderEngine for the given display / config (can't fail) - mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, + getBE().mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0); - LOG_ALWAYS_FATAL_IF(mRenderEngine == nullptr, "couldn't create RenderEngine"); + LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine"); LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, "Starting with vr flinger active is not currently supported."); - getBE().mHwc.reset(new HWComposer(mHwcServiceName)); + getBE().mHwc.reset(new HWComposer(getBE().mHwcServiceName)); getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId); if (useVrFlinger) { @@ -651,7 +651,7 @@ void SurfaceFlinger::init() { // set initial conditions (e.g. unblank default device) initializeDisplays(); - mRenderEngine->primeCache(); + getBE().mRenderEngine->primeCache(); // Inform native graphics APIs whether the present timestamp is supported: if (getHwComposer().hasCapability( @@ -693,11 +693,11 @@ void SurfaceFlinger::startBootAnim() { } size_t SurfaceFlinger::getMaxTextureSize() const { - return mRenderEngine->getMaxTextureSize(); + return getBE().mRenderEngine->getMaxTextureSize(); } size_t SurfaceFlinger::getMaxViewportDims() const { - return mRenderEngine->getMaxViewportDims(); + return getBE().mRenderEngine->getMaxViewportDims(); } // ---------------------------------------------------------------------------- @@ -1411,7 +1411,7 @@ void SurfaceFlinger::updateVrFlinger() { resetDisplayState(); getBE().mHwc.reset(); // Delete the current instance before creating the new one - getBE().mHwc.reset(new HWComposer(vrFlingerRequestsDisplay ? "vr" : mHwcServiceName)); + getBE().mHwc.reset(new HWComposer(vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName)); getBE().mHwc->registerCallback(this, ++getBE().mComposerSequenceId); LOG_ALWAYS_FATAL_IF(!getBE().mHwc->getComposer()->isRemote(), @@ -2672,9 +2672,9 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev if (hasClientComposition) { ALOGV("hasClientComposition"); - mRenderEngine->setWideColor( + getBE().mRenderEngine->setWideColor( displayDevice->getWideColorSupport() && !mForceNativeColorMode); - mRenderEngine->setColorMode(mForceNativeColorMode ? + getBE().mRenderEngine->setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode()); if (!displayDevice->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", @@ -2696,7 +2696,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev // remove where there are opaque FB layers. however, on some // GPUs doing a "clean slate" clear might be more efficient. // We'll revisit later if needed. - mRenderEngine->clearWithColor(0, 0, 0, 0); + getBE().mRenderEngine->clearWithColor(0, 0, 0, 0); } else { // we start with the whole screen area and remove the scissor part // we're left with the letterbox region @@ -2726,7 +2726,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev // enable scissor for this frame const uint32_t height = displayDevice->getHeight(); - mRenderEngine->setScissor(scissor.left, height - scissor.bottom, + getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom, scissor.getWidth(), scissor.getHeight()); } } @@ -2791,7 +2791,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev } // disable scissor at the end of the frame - mRenderEngine->disableScissor(); + getBE().mRenderEngine->disableScissor(); return true; } @@ -3885,7 +3885,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, HWComposer& hwc(getHwComposer()); sp hw(getDefaultDisplayDeviceLocked()); - mRenderEngine->dump(result); + getBE().mRenderEngine->dump(result); hw->undefinedRegion.dump(result, "undefinedRegion"); result.appendFormat(" orientation=%d, isDisplayOn=%d\n", diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 840c5e4d42..55f6ea9346 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -136,6 +136,13 @@ public: // acquiring mStateLock. std::unique_ptr mHwc; + const std::string mHwcServiceName; // "default" for real use, something else for testing. + + // constant members (no synchronization needed for access) + std::unique_ptr mRenderEngine; + EGLContext mEGLContext; + EGLDisplay mEGLDisplay; + // 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. @@ -256,7 +263,7 @@ public: const Vector< sp >& getLayerSortedByZForHwcDisplay(int id); RenderEngine& getRenderEngine() const { - return *mRenderEngine; + return *getBE().mRenderEngine; } bool authenticateSurfaceTextureLocked( @@ -669,10 +676,7 @@ private: // access must be protected by mInvalidateLock volatile int32_t mRepaintEverything; - const std::string mHwcServiceName; // "default" for real use, something else for testing. - // constant members (no synchronization needed for access) - std::unique_ptr mRenderEngine; nsecs_t mBootTime; bool mGpuToCpuSupported; sp mEventThread; -- cgit v1.2.3-59-g8ed1b From 99974d2935a520141d77983ac0329350460f2379 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Tue, 28 Nov 2017 12:04:33 -0800 Subject: SF: CompositorTiming/CompositorPresentTime state to SFBE Add CompositorTiming/CompositorPresentTime state to SurfaceFlingerBE Test: build Change-Id: I49f11953e75f080ecefb295af95539d20315bb7a --- services/surfaceflinger/SurfaceFlinger.cpp | 38 +++++++++++++++--------------- services/surfaceflinger/SurfaceFlinger.h | 20 +++++++++------- 2 files changed, 30 insertions(+), 28 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b9afcc08ab..ce336bfcca 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -228,7 +228,7 @@ SurfaceFlinger::SurfaceFlinger() hasWideColorDisplay = getBool(false); - mPrimaryDispSync.init(hasSyncFramework, dispSyncPresentTimeOffset); + mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset); // debugging stuff... char value[PROPERTY_VALUE_MAX]; @@ -591,11 +591,11 @@ void SurfaceFlinger::init() { Mutex::Autolock _l(mStateLock); // start the EventThread - sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync, - vsyncPhaseOffsetNs, true, "app"); + sp vsyncSrc = + new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app"); mEventThread = new EventThread(vsyncSrc, *this, false); - sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, - sfVsyncPhaseOffsetNs, true, "sf"); + sp sfVsyncSrc = + new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf"); mSFEventThread = new EventThread(sfVsyncSrc, *this, true); mEventQueue.setEventThread(mSFEventThread); @@ -1262,8 +1262,8 @@ void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, } void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { - std::lock_guard lock(mCompositorTimingLock); - *compositorTiming = mCompositorTiming; + std::lock_guard lock(getBE().mCompositorTimingLock); + *compositorTiming = getBE().mCompositorTiming; } void SurfaceFlinger::createDefaultDisplayDevice() { @@ -1598,10 +1598,10 @@ void SurfaceFlinger::updateCompositorTiming( std::shared_ptr& presentFenceTime) { // Update queue of past composite+present times and determine the // most recently known composite to present latency. - mCompositePresentTimes.push({compositeTime, presentFenceTime}); + getBE().mCompositePresentTimes.push({compositeTime, presentFenceTime}); nsecs_t compositeToPresentLatency = -1; - while (!mCompositePresentTimes.empty()) { - CompositePresentTime& cpt = mCompositePresentTimes.front(); + while (!getBE().mCompositePresentTimes.empty()) { + SurfaceFlingerBE::CompositePresentTime& cpt = getBE().mCompositePresentTimes.front(); // Cached values should have been updated before calling this method, // which helps avoid duplicate syscalls. nsecs_t displayTime = cpt.display->getCachedSignalTime(); @@ -1609,12 +1609,12 @@ void SurfaceFlinger::updateCompositorTiming( break; } compositeToPresentLatency = displayTime - cpt.composite; - mCompositePresentTimes.pop(); + getBE().mCompositePresentTimes.pop(); } // Don't let mCompositePresentTimes grow unbounded, just in case. - while (mCompositePresentTimes.size() > 16) { - mCompositePresentTimes.pop(); + while (getBE().mCompositePresentTimes.size() > 16) { + getBE().mCompositePresentTimes.pop(); } setCompositorTimingSnapped( @@ -1646,10 +1646,10 @@ void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase, nsecs_t snappedCompositeToPresentLatency = (extraVsyncs > 0) ? idealLatency + (extraVsyncs * vsyncInterval) : idealLatency; - std::lock_guard lock(mCompositorTimingLock); - mCompositorTiming.deadline = vsyncPhase - idealLatency; - mCompositorTiming.interval = vsyncInterval; - mCompositorTiming.presentLatency = snappedCompositeToPresentLatency; + std::lock_guard lock(getBE().mCompositorTimingLock); + getBE().mCompositorTiming.deadline = vsyncPhase - idealLatency; + getBE().mCompositorTiming.interval = vsyncInterval; + getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency; } void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) @@ -1691,8 +1691,8 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) vsyncPhase, vsyncInterval, refreshStartTime, presentFenceTime); CompositorTiming compositorTiming; { - std::lock_guard lock(mCompositorTimingLock); - compositorTiming = mCompositorTiming; + std::lock_guard lock(getBE().mCompositorTimingLock); + compositorTiming = getBE().mCompositorTiming; } mDrawingState.traverseInZOrder([&](Layer* layer) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 55f6ea9346..be5f72f83f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -143,6 +143,17 @@ public: EGLContext mEGLContext; EGLDisplay mEGLDisplay; + // protected by mCompositorTimingLock; + mutable std::mutex mCompositorTimingLock; + CompositorTiming mCompositorTiming; + + // Only accessed from the main thread. + struct CompositePresentTime { + nsecs_t composite { -1 }; + std::shared_ptr display { FenceTime::NO_FENCE }; + }; + std::queue mCompositePresentTimes; + // 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. @@ -735,16 +746,7 @@ private: bool mPrimaryHWVsyncEnabled; bool mHWVsyncAvailable; - // protected by mCompositorTimingLock; - mutable std::mutex mCompositorTimingLock; - CompositorTiming mCompositorTiming; - // Only accessed from the main thread. - struct CompositePresentTime { - nsecs_t composite { -1 }; - std::shared_ptr display { FenceTime::NO_FENCE }; - }; - std::queue mCompositePresentTimes; std::atomic mRefreshPending{false}; -- cgit v1.2.3-59-g8ed1b From cbaf083d0a916ad4b6264d770594d44e411f4674 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Tue, 7 Nov 2017 14:21:36 -0800 Subject: SF: BufferingStats state to SFBE Move BufferingStats state to SurfaceFlingerBE Test: build Change-Id: I4404607e44b078bb70dca9562c8d3b180702fe15 --- services/surfaceflinger/SurfaceFlinger.cpp | 10 +++---- services/surfaceflinger/SurfaceFlinger.h | 47 +++++++++++++++--------------- 2 files changed, 28 insertions(+), 29 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ce336bfcca..27a0559e5f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3695,8 +3695,8 @@ void SurfaceFlinger::dumpStaticScreenStats(String8& result) const void SurfaceFlinger::recordBufferingStats(const char* layerName, std::vector&& history) { - Mutex::Autolock lock(mBufferingStatsMutex); - auto& stats = mBufferingStats[layerName]; + Mutex::Autolock lock(getBE().mBufferingStatsMutex); + auto& stats = getBE().mBufferingStats[layerName]; for (const auto& segment : history) { if (!segment.usedThirdBuffer) { stats.twoBufferTime += segment.totalTime; @@ -3725,12 +3725,12 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { result.append("Buffering stats:\n"); result.append(" [Layer name] " " \n"); - Mutex::Autolock lock(mBufferingStatsMutex); + Mutex::Autolock lock(getBE().mBufferingStatsMutex); typedef std::tuple BufferTuple; std::map> sorted; - for (const auto& statsPair : mBufferingStats) { + for (const auto& statsPair : getBE().mBufferingStats) { const char* name = statsPair.first.c_str(); - const BufferingStats& stats = statsPair.second; + const SurfaceFlingerBE::BufferingStats& stats = statsPair.second; if (stats.numSegments == 0) { continue; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index be5f72f83f..419d69d608 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -154,6 +154,29 @@ public: }; std::queue mCompositePresentTimes; + // Double- vs. triple-buffering stats + struct BufferingStats { + BufferingStats() + : numSegments(0), + totalTime(0), + twoBufferTime(0), + doubleBufferedTime(0), + tripleBufferedTime(0) {} + + size_t numSegments; + nsecs_t totalTime; + + // "Two buffer" means that a third buffer was never used, whereas + // "double-buffered" means that on average the segment only used two + // buffers (though it may have used a third for some part of the + // segment) + nsecs_t twoBufferTime; + nsecs_t doubleBufferedTime; + nsecs_t tripleBufferedTime; + }; + mutable Mutex mBufferingStatsMutex; + std::unordered_map mBufferingStats; + // 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. @@ -746,8 +769,6 @@ private: bool mPrimaryHWVsyncEnabled; bool mHWVsyncAvailable; - - std::atomic mRefreshPending{false}; /* ------------------------------------------------------------------------ @@ -771,28 +792,6 @@ private: size_t mNumLayers; - // Double- vs. triple-buffering stats - struct BufferingStats { - BufferingStats() - : numSegments(0), - totalTime(0), - twoBufferTime(0), - doubleBufferedTime(0), - tripleBufferedTime(0) {} - - size_t numSegments; - nsecs_t totalTime; - - // "Two buffer" means that a third buffer was never used, whereas - // "double-buffered" means that on average the segment only used two - // buffers (though it may have used a third for some part of the - // segment) - nsecs_t twoBufferTime; - nsecs_t doubleBufferedTime; - nsecs_t tripleBufferedTime; - }; - mutable Mutex mBufferingStatsMutex; - std::unordered_map mBufferingStats; // Verify that transaction is being called by an approved process: // either AID_GRAPHICS or AID_SYSTEM. -- cgit v1.2.3-59-g8ed1b From 4a36e9384d10fe3a1e57599558d68e95ff51279a Mon Sep 17 00:00:00 2001 From: David Sodman Date: Tue, 7 Nov 2017 14:29:47 -0800 Subject: SF: FrameBuckets state to SFBE Move FrameBuckets state to SurfaceFlingerBE Test: build Change-Id: Ib44ab2dc189e0ba31ab8ec5a157c9c3b7cd9808a --- services/surfaceflinger/SurfaceFlinger.cpp | 30 +++++++++++++++--------------- services/surfaceflinger/SurfaceFlinger.h | 9 +++++---- 2 files changed, 20 insertions(+), 19 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 27a0559e5f..cfabef1c34 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -156,6 +156,9 @@ bool useTrebleTestingOverride() { SurfaceFlingerBE::SurfaceFlingerBE() : mHwcServiceName(getHwcServiceName()), mRenderEngine(nullptr), + mFrameBuckets(), + mTotalTime(0), + mLastSwapTime(0), mComposerSequenceId(0) { } @@ -188,9 +191,6 @@ SurfaceFlinger::SurfaceFlinger() mHWVsyncAvailable(false), mHasColorMatrix(false), mHasPoweredOff(false), - mFrameBuckets(), - mTotalTime(0), - mLastSwapTime(0), mNumLayers(0), mVrFlingerRequestsDisplay(false), mMainThreadId(std::this_thread::get_id()) @@ -1742,16 +1742,16 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) if (mHasPoweredOff) { mHasPoweredOff = false; } else { - nsecs_t elapsedTime = currentTime - mLastSwapTime; + nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime; size_t numPeriods = static_cast(elapsedTime / vsyncInterval); - if (numPeriods < NUM_BUCKETS - 1) { - mFrameBuckets[numPeriods] += elapsedTime; + if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) { + getBE().mFrameBuckets[numPeriods] += elapsedTime; } else { - mFrameBuckets[NUM_BUCKETS - 1] += elapsedTime; + getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] += elapsedTime; } - mTotalTime += elapsedTime; + getBE().mTotalTime += elapsedTime; } - mLastSwapTime = currentTime; + getBE().mLastSwapTime = currentTime; } void SurfaceFlinger::rebuildLayerStacks() { @@ -3679,18 +3679,18 @@ void SurfaceFlinger::appendSfConfigString(String8& result) const void SurfaceFlinger::dumpStaticScreenStats(String8& result) const { result.appendFormat("Static screen stats:\n"); - for (size_t b = 0; b < NUM_BUCKETS - 1; ++b) { - float bucketTimeSec = mFrameBuckets[b] / 1e9; + for (size_t b = 0; b < SurfaceFlingerBE::NUM_BUCKETS - 1; ++b) { + float bucketTimeSec = getBE().mFrameBuckets[b] / 1e9; float percent = 100.0f * - static_cast(mFrameBuckets[b]) / mTotalTime; + static_cast(getBE().mFrameBuckets[b]) / getBE().mTotalTime; result.appendFormat(" < %zd frames: %.3f s (%.1f%%)\n", b + 1, bucketTimeSec, percent); } - float bucketTimeSec = mFrameBuckets[NUM_BUCKETS - 1] / 1e9; + float bucketTimeSec = getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] / 1e9; float percent = 100.0f * - static_cast(mFrameBuckets[NUM_BUCKETS - 1]) / mTotalTime; + static_cast(getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1]) / getBE().mTotalTime; result.appendFormat(" %zd+ frames: %.3f s (%.1f%%)\n", - NUM_BUCKETS - 1, bucketTimeSec, percent); + SurfaceFlingerBE::NUM_BUCKETS - 1, bucketTimeSec, percent); } void SurfaceFlinger::recordBufferingStats(const char* layerName, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 419d69d608..85cba987e7 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -154,6 +154,11 @@ public: }; std::queue mCompositePresentTimes; + static const size_t NUM_BUCKETS = 8; // < 1-7, 7+ + nsecs_t mFrameBuckets[NUM_BUCKETS]; + nsecs_t mTotalTime; + std::atomic mLastSwapTime; + // Double- vs. triple-buffering stats struct BufferingStats { BufferingStats() @@ -785,10 +790,6 @@ private: // Static screen stats bool mHasPoweredOff; - static const size_t NUM_BUCKETS = 8; // < 1-7, 7+ - nsecs_t mFrameBuckets[NUM_BUCKETS]; - nsecs_t mTotalTime; - std::atomic mLastSwapTime; size_t mNumLayers; -- cgit v1.2.3-59-g8ed1b From 73bededbdc82a5b6199f0860c8900e75c6f0e467 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Wed, 15 Nov 2017 11:56:06 -0800 Subject: SF: Move glComp/DispTimeline to SFBE Move glCompositionDoneTimeline and mDisplayTimeline to the SurfaceFlingerBE object. Test: Build/run manually Change-Id: I77f2cc39ecf20d5b1c93b5396e37df5b1273d613 --- services/surfaceflinger/Layer.h | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 8 ++++---- services/surfaceflinger/SurfaceFlinger.h | 5 +++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9a98e1e2a6..cf7fc508e8 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -364,7 +364,6 @@ public: void forceClientComposition(int32_t hwcId); bool getForceClientComposition(int32_t hwcId); virtual void setPerFrameData(const sp& displayDevice) = 0; - void setUpFrameBuffer(const sp& displayDevice); // callIntoHwc exists so we can update our local state and call // acceptDisplayChanges without unnecessarily updating the device's state diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cfabef1c34..54695b552c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1666,20 +1666,20 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) // |mStateLock| not needed as we are on the main thread const sp hw(getDefaultDisplayDeviceLocked()); - mGlCompositionDoneTimeline.updateSignalTimes(); + getBE().mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr glCompositionDoneFenceTime; if (getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) { glCompositionDoneFenceTime = std::make_shared(hw->getClientTargetAcquireFence()); - mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime); + getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime); } else { glCompositionDoneFenceTime = FenceTime::NO_FENCE; } - mDisplayTimeline.updateSignalTimes(); + getBE().mDisplayTimeline.updateSignalTimes(); sp presentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); auto presentFenceTime = std::make_shared(presentFence); - mDisplayTimeline.push(presentFenceTime); + getBE().mDisplayTimeline.push(presentFenceTime); nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 85cba987e7..2477bdcfa1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -142,6 +142,9 @@ public: std::unique_ptr mRenderEngine; EGLContext mEGLContext; EGLDisplay mEGLDisplay; + + FenceTimeline mGlCompositionDoneTimeline; + FenceTimeline mDisplayTimeline; // protected by mCompositorTimingLock; mutable std::mutex mCompositorTimingLock; @@ -734,8 +737,6 @@ private: std::vector> mLayersWithQueuedFrames; sp mPreviousPresentFence = Fence::NO_FENCE; bool mHadClientComposition = false; - FenceTimeline mGlCompositionDoneTimeline; - FenceTimeline mDisplayTimeline; // this may only be written from the main thread with mStateLock held // it may be read from other threads with mStateLock held -- cgit v1.2.3-59-g8ed1b From 56a0b9ac6a951053e283cf42e245a48d28d2624c Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 4 Dec 2017 16:06:13 -0800 Subject: Avoid unnecessary calls to updateTransformHint It was observed that this could start to take noticeable time with high layer counts, I guess due to the acquisition of one mutex per layer per call. Anyway it looks like there's no need to call it if a display transaction didn't occur. Test: Existing tests pass. Change-Id: I1918d326a6d0ed32a0a5fea4008a746d328b335d --- services/surfaceflinger/SurfaceFlinger.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 142892e874..03a9df762b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2338,16 +2338,19 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } } } - if (disp == NULL) { - // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to - // redraw after transform hint changes. See bug 8508397. - - // could be null when this layer is using a layerStack - // that is not visible on any display. Also can occur at - // screen off/on times. - disp = getDefaultDisplayDeviceLocked(); + + if (transactionFlags & eDisplayTransactionNeeded) { + if (disp == NULL) { + // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to + // redraw after transform hint changes. See bug 8508397. + + // could be null when this layer is using a layerStack + // that is not visible on any display. Also can occur at + // screen off/on times. + disp = getDefaultDisplayDeviceLocked(); + } + layer->updateTransformHint(disp); } - layer->updateTransformHint(disp); first = false; }); @@ -4613,4 +4616,4 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" -#endif \ No newline at end of file +#endif -- cgit v1.2.3-59-g8ed1b From 51a0b41a6bb7378fd60e96bfb87b820948960187 Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Wed, 6 Dec 2017 17:07:27 -0800 Subject: Fix sanitizer in handleTransitionLocked. The loop as constructed in handleTransitionLocked potentially leads to two unsigned integer overflows on the i = 0 loop on integer sanitized builds. runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long') runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long') This refactors the loop to prevent the overflow. Bug: 30969751 Test: Compiles, device boots. Change-Id: Ia660dffbee3da9667d5e266cc85798eb458660ac --- services/surfaceflinger/SurfaceFlinger.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 555f4a8c35..d1bbfa9033 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2150,7 +2150,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // (ie: in drawing state but not in current state) // also handle displays that changed // (ie: displays that are in both lists) - for (size_t i=0 ; idisconnect(getHwComposer()); mDisplays.removeItem(display); mDrawingState.displays.removeItemsAt(i); - dc--; i--; + dc--; // at this point we must loop to the next item continue; } @@ -2207,6 +2207,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } } } + ++i; } // find displays that were added -- cgit v1.2.3-59-g8ed1b From 767fcf7ef21a2db44ead9e685ebe48f638f3e651 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 30 Nov 2017 22:07:38 -0800 Subject: surfaceflinger: add more sync operations to RenderEngine Add RenderEngine::finish and RenderEngine::waitFence. Rework flush not to fall back to finish. Test: SurfaceFlinger_test Change-Id: I2e5738f72b4aa1186d45d23cab9055f96d90ff23 --- .../surfaceflinger/RenderEngine/GLExtensions.cpp | 10 ++ .../surfaceflinger/RenderEngine/GLExtensions.h | 6 + .../surfaceflinger/RenderEngine/RenderEngine.cpp | 128 +++++++++++++-------- .../surfaceflinger/RenderEngine/RenderEngine.h | 16 ++- services/surfaceflinger/SurfaceFlinger.cpp | 13 ++- 5 files changed, 122 insertions(+), 51 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/GLExtensions.cpp index b7f86640b5..81af21ffed 100644 --- a/services/surfaceflinger/RenderEngine/GLExtensions.cpp +++ b/services/surfaceflinger/RenderEngine/GLExtensions.cpp @@ -89,6 +89,16 @@ void GLExtensions::initWithEGLStrings(char const* eglVersion, char const* eglExt hasEGLExtension("EGL_KHR_no_config_context")) { mHasNoConfigContext = true; } + + if (hasEGLExtension("EGL_ANDROID_native_fence_sync")) { + mHasNativeFenceSync = true; + } + if (hasEGLExtension("EGL_KHR_fence_sync")) { + mHasFenceSync = true; + } + if (hasEGLExtension("EGL_KHR_wait_sync")) { + mHasWaitSync = true; + } } char const* GLExtensions::getEGLVersion() const { diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.h b/services/surfaceflinger/RenderEngine/GLExtensions.h index 47f2f67c9e..1ec0fd915f 100644 --- a/services/surfaceflinger/RenderEngine/GLExtensions.h +++ b/services/surfaceflinger/RenderEngine/GLExtensions.h @@ -36,6 +36,9 @@ class GLExtensions : public Singleton { friend class Singleton; bool mHasNoConfigContext = false; + bool mHasNativeFenceSync = false; + bool mHasFenceSync = false; + bool mHasWaitSync = false; String8 mVendor; String8 mRenderer; @@ -57,6 +60,9 @@ protected: public: bool hasNoConfigContext() const { return mHasNoConfigContext; } + bool hasNativeFenceSync() const { return mHasNativeFenceSync; } + bool hasFenceSync() const { return mHasFenceSync; } + bool hasWaitSync() const { return mHasWaitSync; } void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version, GLubyte const* extensions); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index d3bda17eb0..d5471ad943 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -169,6 +169,88 @@ void RenderEngine::resetCurrentSurface() { eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } +base::unique_fd RenderEngine::flush() { + if (!GLExtensions::getInstance().hasNativeFenceSync()) { + return base::unique_fd(); + } + + EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); + if (sync == EGL_NO_SYNC_KHR) { + ALOGW("failed to create EGL native fence sync: %#x", eglGetError()); + return base::unique_fd(); + } + + // native fence fd will not be populated until flush() is done. + glFlush(); + + // get the fence fd + base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync)); + eglDestroySyncKHR(mEGLDisplay, sync); + if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { + ALOGW("failed to dup EGL native fence sync: %#x", eglGetError()); + } + + return fenceFd; +} + +bool RenderEngine::finish() { + if (!GLExtensions::getInstance().hasFenceSync()) { + ALOGW("no synchronization support"); + return false; + } + + EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL); + if (sync == EGL_NO_SYNC_KHR) { + ALOGW("failed to create EGL fence sync: %#x", eglGetError()); + return false; + } + + EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, + 2000000000 /*2 sec*/); + EGLint error = eglGetError(); + eglDestroySyncKHR(mEGLDisplay, sync); + if (result != EGL_CONDITION_SATISFIED_KHR) { + if (result == EGL_TIMEOUT_EXPIRED_KHR) { + ALOGW("fence wait timed out"); + } else { + ALOGW("error waiting on EGL fence: %#x", error); + } + return false; + } + + return true; +} + +bool RenderEngine::waitFence(base::unique_fd fenceFd) { + if (!GLExtensions::getInstance().hasNativeFenceSync() || + !GLExtensions::getInstance().hasWaitSync()) { + return false; + } + + EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE}; + EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); + if (sync == EGL_NO_SYNC_KHR) { + ALOGE("failed to create EGL native fence sync: %#x", eglGetError()); + return false; + } + + // fenceFd is now owned by EGLSync + (void)fenceFd.release(); + + // XXX: The spec draft is inconsistent as to whether this should return an + // EGLint or void. Ignore the return value for now, as it's not strictly + // needed. + eglWaitSyncKHR(mEGLDisplay, sync, 0); + EGLint error = eglGetError(); + eglDestroySyncKHR(mEGLDisplay, sync); + if (error != EGL_SUCCESS) { + ALOGE("failed to wait for EGL native fence sync: %#x", error); + return false; + } + + return true; +} + void RenderEngine::checkErrors() const { do { // there could be more than one error flag @@ -220,52 +302,6 @@ void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, fl drawMesh(mesh); } -int RenderEngine::flush(bool wait) { - // Attempt to create a sync khr object that can produce a sync point. If that - // isn't available, create a non-dupable sync object in the fallback path and - // wait on it directly. - EGLSyncKHR sync; - if (!wait) { - EGLint syncFd = EGL_NO_NATIVE_FENCE_FD_ANDROID; - - sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); - if (sync != EGL_NO_SYNC_KHR) { - // native fence fd will not be populated until flush() is done. - glFlush(); - - // get the sync fd - syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync); - if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { - ALOGW("failed to dup sync khr object"); - } - - eglDestroySyncKHR(mEGLDisplay, sync); - } - - if (syncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID) { - return syncFd; - } - } - - // fallback or explicit wait - sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL); - if (sync != EGL_NO_SYNC_KHR) { - EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, - 2000000000 /*2 sec*/); - EGLint eglErr = eglGetError(); - if (result == EGL_TIMEOUT_EXPIRED_KHR) { - ALOGW("fence wait timed out"); - } else { - ALOGW_IF(eglErr != EGL_SUCCESS, "error waiting on EGL fence: %#x", eglErr); - } - eglDestroySyncKHR(mEGLDisplay, sync); - } else { - ALOGW("error creating EGL fence: %#x", eglGetError()); - } - - return -1; -} - void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) { glClearColor(red, green, blue, alpha); glClear(GL_COLOR_BUFFER_BIT); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 3847347773..32c669f3aa 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -82,9 +83,20 @@ public: // dump the extension strings. always call the base class. virtual void dump(String8& result); + // synchronization + + // flush submits RenderEngine command stream for execution and returns a + // native fence fd that is signaled when the execution has completed. It + // returns -1 on errors. + base::unique_fd flush(); + // finish waits until RenderEngine command stream has been executed. It + // returns false on errors. + bool finish(); + // waitFence inserts a wait on an external fence fd to RenderEngine + // command stream. It returns false on errors. + bool waitFence(base::unique_fd fenceFd); + // helpers - // flush returns -1 or a valid native fence fd owned by the caller - int flush(bool wait); void clearWithColor(float red, float green, float blue, float alpha); void fillRegionWithColor(const Region& region, uint32_t height, float red, float green, float blue, float alpha); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 44d5ce4fd3..a5b92b5f37 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4538,9 +4538,10 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, // dependent on the context's EGLConfig. renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform); - *outSyncFd = getRenderEngine().flush(DEBUG_SCREENSHOTS); - if (DEBUG_SCREENSHOTS) { + getRenderEngine().finish(); + *outSyncFd = -1; + const auto reqWidth = renderArea.getReqWidth(); const auto reqHeight = renderArea.getReqHeight(); @@ -4548,6 +4549,12 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels); checkScreenshot(reqWidth, reqHeight, reqWidth, pixels, traverseLayers); delete [] pixels; + } else { + base::unique_fd syncFd = getRenderEngine().flush(); + if (syncFd < 0) { + getRenderEngine().finish(); + } + *outSyncFd = syncFd.release(); } return NO_ERROR; @@ -4618,4 +4625,4 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" -#endif \ No newline at end of file +#endif -- cgit v1.2.3-59-g8ed1b From 03480e23a6abd6c25aa3b689f736eb9c051eb8c3 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Thu, 4 Jan 2018 16:02:06 -0800 Subject: Restore ability of system to screenshot secure layers. In previous iterations of the code the "secureLayerIsVisible" block had a guard for "localProducer" which was set to true if the IGBP we were screenshotting to was originally allocated by SurfaceFlinger. What this means is that it came from a SurfaceControl, rather than just being allocated on the client side. Note that the caller could still read the Screenshot back out from the surface, so the old logic just ensured you can't screenshot secure layers unless you have a SurfaceControl. Having a SurfaceControl meant you had either the permission ACCESS_SURFACE_FLINGER, were from AID_SYSTEM/AID_GRAPHICS, or had been granted a SurfaceControl. This allowed the system server to screenshot secure layers for the screen rotation animation. When switching to the GraphicBuffer based interface we eliminated this permisivity. This CL reintroduces it in what is hopefully a clearer way, by explicitly only granting the ability to system components. Bug: 70403018 Test: Manual Change-Id: Icbc51e897f5d46838a68c1387e993b8e6a68cd1d --- services/surfaceflinger/SurfaceFlinger.cpp | 11 +++++++++-- services/surfaceflinger/SurfaceFlinger.h | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7e308e811e..db13b99dcc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4400,6 +4400,9 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, int syncFd = -1; std::optional captureResult; + const int uid = IPCThreadState::self()->getCallingUid(); + const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM; + sp message = new LambdaMessage([&]() { // If there is a refresh pending, bug out early and tell the binder thread to try again // after the refresh. @@ -4416,7 +4419,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, { Mutex::Autolock _l(mStateLock); result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), - useIdentityTransform, &fd); + useIdentityTransform, forSystem, &fd); } { @@ -4513,6 +4516,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, + bool forSystem, int* outSyncFd) { ATRACE_CALL(); @@ -4522,7 +4526,10 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure()); }); - if (secureLayerIsVisible) { + // We allow the system server to take screenshots of secure layers for + // use in situations like the Screen-rotation animation and place + // the impetus on WindowManager to not persist them. + if (secureLayerIsVisible && !forSystem) { ALOGW("FB is protected: PERMISSION_DENIED"); return PERMISSION_DENIED; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2477bdcfa1..8030fbdc41 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -524,7 +524,7 @@ private: status_t captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, - int* outSyncFd); + bool forSystem, int* outSyncFd); void traverseLayersInDisplay(const sp& display, int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor); -- cgit v1.2.3-59-g8ed1b From 87704c94fac81f625ba5b25548fd4ad497500f58 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 8 Jan 2018 15:32:57 -0800 Subject: Get layer trace status from SurfaceFlinger service Bug: 64831661 Test: Toggle layer trace from new QS Tile Change-Id: I7259dbb295feefd2302b0e93c8e1ed1a857616bf --- services/surfaceflinger/SurfaceFlinger.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index db13b99dcc..1341e1744a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4245,7 +4245,7 @@ status_t SurfaceFlinger::onTransact( reply->writeBool(hasWideColorDisplay); return NO_ERROR; } - case 1025: { // tracing + case 1025: { // Set layer tracing n = data.readInt32(); if (n) { ALOGV("LayerTracing enabled"); @@ -4259,6 +4259,10 @@ status_t SurfaceFlinger::onTransact( } return NO_ERROR; } + case 1026: { // Get layer tracing status + reply->writeBool(mTracing.isEnabled()); + return NO_ERROR; + } } } return err; @@ -4306,7 +4310,7 @@ status_t SurfaceFlinger::captureScreen(const sp& display, sp& layerHandleBinder, - sp* outBuffer, const Rect& sourceCrop, + sp* outBuffer, const Rect& sourceCrop, float frameScale) { ATRACE_CALL(); -- cgit v1.2.3-59-g8ed1b From 566a3b4a1d1a2a6d38257113700eea92aa44ea2b Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 9 Jan 2018 18:22:43 -0800 Subject: [SurfaceFlinger] Replace NULL with nullptr. Test: make Change-Id: Ia0ecb3160cd5fddf22fb7100c1759d62e723d0b7 --- services/surfaceflinger/BufferLayer.cpp | 11 ++--- services/surfaceflinger/BufferLayerConsumer.cpp | 20 ++++----- services/surfaceflinger/BufferLayerConsumer.h | 4 +- services/surfaceflinger/Client.cpp | 4 +- services/surfaceflinger/DisplayDevice.cpp | 2 +- .../DisplayHardware/FramebufferSurface.h | 2 +- .../DisplayHardware/HWComposer_hwc1.h | 8 ++-- .../DisplayHardware/VirtualDisplaySurface.cpp | 6 +-- services/surfaceflinger/EventThread.cpp | 4 +- services/surfaceflinger/FrameTracker.cpp | 16 +++---- services/surfaceflinger/FrameTracker.h | 2 +- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/LayerRejecter.cpp | 2 +- services/surfaceflinger/RenderEngine/Program.cpp | 2 +- .../surfaceflinger/RenderEngine/ProgramCache.cpp | 4 +- .../surfaceflinger/RenderEngine/RenderEngine.cpp | 18 ++++---- services/surfaceflinger/SurfaceFlinger.cpp | 50 +++++++++++----------- .../tests/SurfaceInterceptor_test.cpp | 2 +- services/surfaceflinger/tests/Transaction_test.cpp | 16 +++---- 19 files changed, 88 insertions(+), 87 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 5f70ab54da..d860f58509 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -105,7 +105,8 @@ bool BufferLayer::isProtected() const { bool BufferLayer::isVisible() const { return !(isHiddenByPolicy()) && getAlpha() > 0.0f && - (getBE().compositionInfo.mBuffer != NULL || getBE().compositionInfo.hwc.sidebandStream != NULL); + (getBE().compositionInfo.mBuffer != nullptr || + getBE().compositionInfo.hwc.sidebandStream != nullptr); } bool BufferLayer::isFixedSize() const { @@ -377,7 +378,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime mSidebandStream = mConsumer->getSidebandStream(); // replicated in LayerBE until FE/BE is ready to be synchronized getBE().compositionInfo.hwc.sidebandStream = mSidebandStream; - if (getBE().compositionInfo.hwc.sidebandStream != NULL) { + if (getBE().compositionInfo.hwc.sidebandStream != nullptr) { setTransactionFlags(eTransactionNeeded); mFlinger->setTransactionFlags(eTraversalNeeded); } @@ -492,7 +493,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime mConsumer->getCurrentBuffer(&getBE().compositionInfo.mBufferSlot); // replicated in LayerBE until FE/BE is ready to be synchronized mActiveBuffer = getBE().compositionInfo.mBuffer; - if (getBE().compositionInfo.mBuffer == NULL) { + if (getBE().compositionInfo.mBuffer == nullptr) { // this can only happen if the very first buffer was rejected. return outDirtyRegion; } @@ -508,7 +509,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime mRefreshPending = true; mFrameLatencyNeeded = true; - if (oldBuffer == NULL) { + if (oldBuffer == nullptr) { // the first time we receive a buffer, we need to trigger a // geometry invalidation. recomputeVisibleRegions = true; @@ -528,7 +529,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime recomputeVisibleRegions = true; } - if (oldBuffer != NULL) { + if (oldBuffer != nullptr) { uint32_t bufWidth = getBE().compositionInfo.mBuffer->getWidth(); uint32_t bufHeight = getBE().compositionInfo.mBuffer->getHeight(); if (bufWidth != uint32_t(oldBuffer->width) || diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index bf61236663..8f5c9c740b 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -271,7 +271,7 @@ status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t pres // If item->mGraphicBuffer is not null, this buffer has not been acquired // before, so any prior EglImage created is using a stale buffer. This // replaces any old EglImage with a new one (using the new buffer). - if (item->mGraphicBuffer != NULL) { + if (item->mGraphicBuffer != nullptr) { mImages[item->mSlot] = new Image(item->mGraphicBuffer, mRE); } @@ -306,8 +306,8 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, } BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, - mCurrentTextureImage != NULL ? mCurrentTextureImage->graphicBufferHandle() : 0, slot, - mSlots[slot].mGraphicBuffer->handle); + mCurrentTextureImage != nullptr ? mCurrentTextureImage->graphicBufferHandle() : 0, + slot, mSlots[slot].mGraphicBuffer->handle); // Hang onto the pointer so that it isn't freed in the call to // releaseBufferLocked() if we're in shared buffer mode and both buffers are @@ -355,7 +355,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, status_t BufferLayerConsumer::bindTextureImageLocked() { mRE.checkErrors(); - if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == NULL) { + if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == nullptr) { BLC_LOGE("bindTextureImage: no currently-bound texture"); mRE.bindExternalTextureImage(mTexName, RE::Image(mRE)); return NO_INIT; @@ -414,11 +414,11 @@ void BufferLayerConsumer::setFilteringEnabled(bool enabled) { bool needsRecompute = mFilteringEnabled != enabled; mFilteringEnabled = enabled; - if (needsRecompute && mCurrentTextureImage == NULL) { - BLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL"); + if (needsRecompute && mCurrentTextureImage == nullptr) { + BLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == nullptr"); } - if (needsRecompute && mCurrentTextureImage != NULL) { + if (needsRecompute && mCurrentTextureImage != nullptr) { computeCurrentTransformMatrixLocked(); } } @@ -429,7 +429,7 @@ void BufferLayerConsumer::computeCurrentTransformMatrixLocked() { (mCurrentTextureImage == nullptr) ? nullptr : mCurrentTextureImage->graphicBuffer(); if (buf == nullptr) { BLC_LOGD("computeCurrentTransformMatrixLocked: " - "mCurrentTextureImage is NULL"); + "mCurrentTextureImage is nullptr"); } const Rect& cropRect = canUseImageCrop(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop; GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, buf, cropRect, mCurrentTransform, @@ -476,7 +476,7 @@ sp BufferLayerConsumer::getCurrentBuffer(int* outSlot) const { *outSlot = mCurrentTexture; } - return (mCurrentTextureImage == nullptr) ? NULL : mCurrentTextureImage->graphicBuffer(); + return (mCurrentTextureImage == nullptr) ? nullptr : mCurrentTextureImage->graphicBuffer(); } Rect BufferLayerConsumer::getCurrentCrop() const { @@ -564,7 +564,7 @@ void BufferLayerConsumer::onSidebandStreamChanged() { listener = mContentsChangedListener.promote(); } - if (listener != NULL) { + if (listener != nullptr) { listener->onSidebandStreamChanged(); } } diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index 51c2b414d7..f473390ea7 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -228,7 +228,7 @@ private: const sp& graphicBuffer() { return mGraphicBuffer; } const native_handle* graphicBufferHandle() { - return mGraphicBuffer == NULL ? NULL : mGraphicBuffer->handle; + return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle; } const RE::Image& image() const { return mImage; } @@ -265,7 +265,7 @@ private: // computeCurrentTransformMatrixLocked computes the transform matrix for the // current texture. It uses mCurrentTransform and the current GraphicBuffer // to compute this matrix and stores it in mCurrentTransformMatrix. - // mCurrentTextureImage must not be NULL. + // mCurrentTextureImage must not be nullptr. void computeCurrentTransformMatrixLocked(); // doFenceWaitLocked inserts a wait command into the RenderEngine command diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index ea6541a734..a69940a42e 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -206,7 +206,7 @@ status_t Client::destroySurface(const sp& handle) { status_t Client::clearLayerFrameStats(const sp& handle) const { sp layer = getLayerUser(handle); - if (layer == NULL) { + if (layer == nullptr) { return NAME_NOT_FOUND; } layer->clearFrameStats(); @@ -215,7 +215,7 @@ status_t Client::clearLayerFrameStats(const sp& handle) const { status_t Client::getLayerFrameStats(const sp& handle, FrameStats* outStats) const { sp layer = getLayerUser(handle); - if (layer == NULL) { + if (layer == nullptr) { return NAME_NOT_FOUND; } layer->getFrameStats(outStats); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 2753f11097..9772f9a1be 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -160,7 +160,7 @@ void DisplayDevice::disconnect(HWComposer& hwc) { } bool DisplayDevice::isValid() const { - return mFlinger != NULL; + return mFlinger != nullptr; } int DisplayDevice::getWidth() const { diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 4186b7aac4..eaa54553ed 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -80,7 +80,7 @@ private: // on/off. android_dataspace mDataSpace; - // mCurrentBuffer is the current buffer or NULL to indicate that there is + // mCurrentBuffer is the current buffer or nullptr to indicate that there is // no current buffer. sp mCurrentBuffer; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h index 4bc63bbac8..fe7944f635 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h @@ -190,7 +190,7 @@ public: virtual status_t setLayer(size_t index) = 0; virtual HWCLayer* dup() = 0; static HWCLayer* copy(HWCLayer *rhs) { - return rhs ? rhs->dup() : NULL; + return rhs ? rhs->dup() : nullptr; } protected: virtual ~HWCLayer() { } @@ -205,7 +205,7 @@ public: HWCLayer* const mLayerList; size_t mIndex; - LayerListIterator() : mLayerList(NULL), mIndex(0) { } + LayerListIterator() : mLayerList(nullptr), mIndex(0) { } LayerListIterator(HWCLayer* layer, size_t index) : mLayerList(layer), mIndex(index) { } @@ -371,8 +371,8 @@ private: sp mFlinger; framebuffer_device_t* mFbDev; struct hwc_composer_device_1* mHwc; - // invariant: mLists[0] != NULL iff mHwc != NULL - // mLists[i>0] can be NULL. that display is to be ignored + // invariant: mLists[0] != nullptr iff mHwc != nullptr + // mLists[i>0] can be nullptr. that display is to be ignored struct hwc_display_contents_1* mLists[MAX_HWC_DISPLAYS]; DisplayData mDisplayData[MAX_HWC_DISPLAYS]; // protect mDisplayData from races between prepare and dump diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index cde96e4162..3480b24390 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -108,7 +108,7 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight); sink->setAsyncMode(true); IGraphicBufferProducer::QueueBufferOutput output; - mSource[SOURCE_SCRATCH]->connect(NULL, NATIVE_WINDOW_API_EGL, false, &output); + mSource[SOURCE_SCRATCH]->connect(nullptr, NATIVE_WINDOW_API_EGL, false, &output); } VirtualDisplaySurface::~VirtualDisplaySurface() { @@ -203,7 +203,7 @@ status_t VirtualDisplaySurface::advanceFrame() { } sp fbBuffer = mFbProducerSlot >= 0 ? - mProducerBuffers[mFbProducerSlot] : sp(NULL); + mProducerBuffers[mFbProducerSlot] : sp(nullptr); sp outBuffer = mProducerBuffers[mOutputProducerSlot]; VDS_LOGV("advanceFrame: fb=%d(%p) out=%d(%p)", mFbProducerSlot, fbBuffer.get(), @@ -214,7 +214,7 @@ status_t VirtualDisplaySurface::advanceFrame() { mHwc.setOutputBuffer(mDisplayId, mOutputFence, outBuffer); status_t result = NO_ERROR; - if (fbBuffer != NULL) { + if (fbBuffer != nullptr) { uint32_t hwcSlot = 0; sp hwcBuffer; mHwcBufferCache.getHwcBuffer(mFbProducerSlot, fbBuffer, diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index a1a042039c..5c0e3b37f3 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -216,7 +216,7 @@ Vector< sp > EventThread::waitForEvent( size_t count = mDisplayEventConnections.size(); for (size_t i=0 ; i connection(mDisplayEventConnections[i].promote()); - if (connection != NULL) { + if (connection != nullptr) { bool added = false; if (connection->count >= 0) { // we need vsync events because at least @@ -346,7 +346,7 @@ void EventThread::dump(String8& result) const { sp connection = mDisplayEventConnections.itemAt(i).promote(); result.appendFormat(" %p: count=%d\n", - connection.get(), connection!=NULL ? connection->count : 0); + connection.get(), connection != nullptr ? connection->count : 0); } } diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp index 99c4daaba5..1539873aaa 100644 --- a/services/surfaceflinger/FrameTracker.cpp +++ b/services/surfaceflinger/FrameTracker.cpp @@ -82,17 +82,17 @@ void FrameTracker::advanceFrame() { mFrameRecords[mOffset].frameReadyTime = INT64_MAX; mFrameRecords[mOffset].actualPresentTime = INT64_MAX; - if (mFrameRecords[mOffset].frameReadyFence != NULL) { + if (mFrameRecords[mOffset].frameReadyFence != nullptr) { // We're clobbering an unsignaled fence, so we need to decrement the // fence count. - mFrameRecords[mOffset].frameReadyFence = NULL; + mFrameRecords[mOffset].frameReadyFence = nullptr; mNumFences--; } - if (mFrameRecords[mOffset].actualPresentFence != NULL) { + if (mFrameRecords[mOffset].actualPresentFence != nullptr) { // We're clobbering an unsignaled fence, so we need to decrement the // fence count. - mFrameRecords[mOffset].actualPresentFence = NULL; + mFrameRecords[mOffset].actualPresentFence = nullptr; mNumFences--; } } @@ -153,10 +153,10 @@ void FrameTracker::processFencesLocked() const { bool updated = false; const std::shared_ptr& rfence = records[idx].frameReadyFence; - if (rfence != NULL) { + if (rfence != nullptr) { records[idx].frameReadyTime = rfence->getSignalTime(); if (records[idx].frameReadyTime < INT64_MAX) { - records[idx].frameReadyFence = NULL; + records[idx].frameReadyFence = nullptr; numFences--; updated = true; } @@ -164,10 +164,10 @@ void FrameTracker::processFencesLocked() const { const std::shared_ptr& pfence = records[idx].actualPresentFence; - if (pfence != NULL) { + if (pfence != nullptr) { records[idx].actualPresentTime = pfence->getSignalTime(); if (records[idx].actualPresentTime < INT64_MAX) { - records[idx].actualPresentFence = NULL; + records[idx].actualPresentFence = nullptr; numFences--; updated = true; } diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h index adcdfb528d..b4a9fd68fb 100644 --- a/services/surfaceflinger/FrameTracker.h +++ b/services/surfaceflinger/FrameTracker.h @@ -35,7 +35,7 @@ class String8; // possible. // // Some of the time values tracked may be set either as a specific timestamp -// or a fence. When a non-NULL fence is set for a given time value, the +// or a fence. When a non-nullptr fence is set for a given time value, the // signal time of that fence is used instead of the timestamp. class FrameTracker { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index cc675c491b..63f6781f02 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -265,7 +265,7 @@ Rect Layer::getContentCrop() const { if (!mCurrentCrop.isEmpty()) { // if the buffer crop is defined, we use that crop = mCurrentCrop; - } else if (getBE().compositionInfo.mBuffer != NULL) { + } else if (getBE().compositionInfo.mBuffer != nullptr) { // otherwise we use the whole buffer crop = getBE().compositionInfo.mBuffer->getBounds(); } else { diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index e8646076a5..a5f0b9878c 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -41,7 +41,7 @@ LayerRejecter::LayerRejecter(Layer::State& front, mFreezeGeometryUpdates(freezePositionUpdates) {} bool LayerRejecter::reject(const sp& buf, const BufferItem& item) { - if (buf == NULL) { + if (buf == nullptr) { return false; } diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp index baf92ebf60..225bcf0327 100644 --- a/services/surfaceflinger/RenderEngine/Program.cpp +++ b/services/surfaceflinger/RenderEngine/Program.cpp @@ -115,7 +115,7 @@ String8& Program::dumpShader(String8& result, GLenum /*type*/) { GLint l; glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &l); char* src = new char[l]; - glGetShaderSource(shader, l, NULL, src); + glGetShaderSource(shader, l, nullptr, src); result.append(src); delete[] src; return result; diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index 4f138dc14c..3b8ac0e58c 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -98,7 +98,7 @@ void ProgramCache::primeCache() { continue; } Program* program = mCache.valueFor(shaderKey); - if (program == NULL) { + if (program == nullptr) { program = generateProgram(shaderKey); mCache.add(shaderKey, program); shaderCount++; @@ -273,7 +273,7 @@ void ProgramCache::useProgram(const Description& description) { // look-up the program in the cache Program* program = mCache.valueFor(needs); - if (program == NULL) { + if (program == nullptr) { // we didn't find our program, so generate one... nsecs_t time = -systemTime(); program = generateProgram(needs); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 314333f044..179b79003c 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -36,11 +36,11 @@ namespace android { std::unique_ptr RenderEngine::create(int hwcFormat, uint32_t featureFlags) { // initialize EGL for the default display EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (!eglInitialize(display, NULL, NULL)) { + if (!eglInitialize(display, nullptr, nullptr)) { LOG_ALWAYS_FATAL("failed to initialize EGL"); } - GLExtensions& extensions(GLExtensions::getInstance()); + GLExtensions& extensions = GLExtensions::getInstance(); extensions.initWithEGLStrings(eglQueryStringImplementationANDROID(display, EGL_VERSION), eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS)); @@ -79,7 +79,7 @@ std::unique_ptr RenderEngine::create(int hwcFormat, uint32_t featu contextAttributes.push_back(EGL_NONE); contextAttributes.push_back(EGL_NONE); - EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes.data()); + EGLContext ctxt = eglCreateContext(display, config, nullptr, contextAttributes.data()); // if can't create a GL context, we can only abort. LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed"); @@ -132,7 +132,7 @@ std::unique_ptr RenderEngine::create(int hwcFormat, uint32_t featu } RenderEngine::RenderEngine() - : mEGLDisplay(EGL_NO_DISPLAY), mEGLConfig(NULL), mEGLContext(EGL_NO_CONTEXT) {} + : mEGLDisplay(EGL_NO_DISPLAY), mEGLConfig(nullptr), mEGLContext(EGL_NO_CONTEXT) {} RenderEngine::~RenderEngine() { eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); @@ -183,7 +183,7 @@ base::unique_fd RenderEngine::flush() { return base::unique_fd(); } - EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); + EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr); if (sync == EGL_NO_SYNC_KHR) { ALOGW("failed to create EGL native fence sync: %#x", eglGetError()); return base::unique_fd(); @@ -208,7 +208,7 @@ bool RenderEngine::finish() { return false; } - EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL); + EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr); if (sync == EGL_NO_SYNC_KHR) { ALOGW("failed to create EGL fence sync: %#x", eglGetError()); return false; @@ -347,7 +347,7 @@ void RenderEngine::readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* } void RenderEngine::dump(String8& result) { - const GLExtensions& extensions(GLExtensions::getInstance()); + const GLExtensions& extensions = GLExtensions::getInstance(); result.appendFormat("EGL implementation : %s\n", extensions.getEGLVersion()); result.appendFormat("%s\n", extensions.getEGLExtensions()); @@ -363,7 +363,7 @@ RenderEngine::BindNativeBufferAsFramebuffer::BindNativeBufferAsFramebuffer( RenderEngine& engine, ANativeWindowBuffer* buffer) : mEngine(engine) { mImage = eglCreateImageKHR(mEngine.mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, - buffer, NULL); + buffer, nullptr); if (mImage == EGL_NO_IMAGE_KHR) { mStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; return; @@ -394,7 +394,7 @@ status_t RenderEngine::BindNativeBufferAsFramebuffer::getStatus() const { static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute, EGLint wanted, EGLConfig* outConfig) { EGLint numConfigs = -1, n = 0; - eglGetConfigs(dpy, NULL, 0, &numConfigs); + eglGetConfigs(dpy, nullptr, 0, &numConfigs); EGLConfig* const configs = new EGLConfig[numConfigs]; eglChooseConfig(dpy, attrs, configs, numConfigs, &n); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index db13b99dcc..0210592c81 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -382,7 +382,7 @@ void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) sp SurfaceFlinger::getBuiltInDisplay(int32_t id) { if (uint32_t(id) >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id); - return NULL; + return nullptr; } return mBuiltinDisplays[id]; } @@ -531,7 +531,7 @@ private: } } - if (callback != NULL) { + if (callback != nullptr) { callback->onVSyncEvent(when); } } @@ -737,7 +737,7 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps( status_t SurfaceFlinger::getDisplayConfigs(const sp& display, Vector* configs) { - if ((configs == NULL) || (display.get() == NULL)) { + if (configs == nullptr || display.get() == nullptr) { return BAD_VALUE; } @@ -761,7 +761,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, static int getDensityFromProperty(char const* propName) { char property[PROPERTY_VALUE_MAX]; int density = 0; - if (property_get(propName, property, NULL) > 0) { + if (property_get(propName, property, nullptr) > 0) { density = atoi(property); } return density; @@ -842,7 +842,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, status_t SurfaceFlinger::getDisplayStats(const sp& /* display */, DisplayStatInfo* stats) { - if (stats == NULL) { + if (stats == nullptr) { return BAD_VALUE; } @@ -854,13 +854,13 @@ status_t SurfaceFlinger::getDisplayStats(const sp& /* display */, } int SurfaceFlinger::getActiveConfig(const sp& display) { - if (display == NULL) { - ALOGE("%s : display is NULL", __func__); + if (display == nullptr) { + ALOGE("%s : display is nullptr", __func__); return BAD_VALUE; } sp device(getDisplayDevice(display)); - if (device != NULL) { + if (device != nullptr) { return device->getActiveConfig(); } @@ -905,7 +905,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp& display, int mode) { return true; } sp hw(mFlinger.getDisplayDevice(mDisplay)); - if (hw == NULL) { + if (hw == nullptr) { ALOGE("Attempt to set active config = %d for null display %p", mMode, mDisplay.get()); } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) { @@ -2165,7 +2165,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) const sp defaultDisplay(getDefaultDisplayDeviceLocked()); defaultDisplay->makeCurrent(); sp hw(getDisplayDeviceLocked(draw.keyAt(i))); - if (hw != NULL) + if (hw != nullptr) hw->disconnect(getHwComposer()); if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) mEventThread->onHotplugReceived(draw[i].type, false); @@ -2185,7 +2185,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // from the drawing state, so that it get re-added // below. sp hw(getDisplayDeviceLocked(display)); - if (hw != NULL) + if (hw != nullptr) hw->disconnect(getHwComposer()); mDisplays.removeItem(display); mDrawingState.displays.removeItemsAt(i); @@ -2195,7 +2195,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } const sp disp(getDisplayDeviceLocked(display)); - if (disp != NULL) { + if (disp != nullptr) { if (state.layerStack != draw[i].layerStack) { disp->setLayerStack(state.layerStack); } @@ -2231,7 +2231,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // Virtual displays without a surface are dormant: // they have external state (layer stack, projection, // etc.) but no internal state (i.e. a DisplayDevice). - if (state.surface != NULL) { + if (state.surface != nullptr) { // Allow VR composer to use virtual displays. if (mUseHwcVirtualDisplays || getBE().mHwc->isUsingVrComposer()) { @@ -2268,7 +2268,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) producer = vds; } } else { - ALOGE_IF(state.surface!=NULL, + ALOGE_IF(state.surface != nullptr, "adding a supported display, but rendering " "surface is provided (%p), ignoring it", state.surface.get()); @@ -2279,7 +2279,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } const wp& display(curr.keyAt(i)); - if (dispSurface != NULL) { + if (dispSurface != nullptr) { sp hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, dispSurface, producer, hasWideColorDisplay); @@ -2334,10 +2334,10 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) for (size_t dpy=0 ; dpy hw(mDisplays[dpy]); if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) { - if (disp == NULL) { + if (disp == nullptr) { disp = std::move(hw); } else { - disp = NULL; + disp = nullptr; break; } } @@ -2345,7 +2345,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } if (transactionFlags & eDisplayTransactionNeeded) { - if (disp == NULL) { + if (disp == nullptr) { // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to // redraw after transform hint changes. See bug 8508397. @@ -2941,16 +2941,16 @@ void SurfaceFlinger::setTransactionState( for (size_t i=0 ; i binder = IInterface::asBinder(s.client); - if (binder != NULL) { - if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != NULL) { + if (binder != nullptr) { + if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != nullptr) { sp client( static_cast(s.client.get()) ); transactionFlags |= setClientStateLocked(client, s.state); } @@ -3324,7 +3324,7 @@ status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp l(client->getLayerUser(handle)); - if (l != NULL) { + if (l != nullptr) { mInterceptor.saveSurfaceDeletion(l); err = removeLayer(l); ALOGE_IF(err<0 && err != NAME_NOT_FOUND, @@ -3489,7 +3489,7 @@ void SurfaceFlinger::setPowerMode(const sp& display, int mode) { mDisplay(disp) { mMode = mode; } virtual bool handler() { sp hw(mFlinger.getDisplayDevice(mDisplay)); - if (hw == NULL) { + if (hw == nullptr) { ALOGE("Attempt to set power mode = %d for null display %p", mMode, mDisplay.get()); } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) { @@ -3978,7 +3978,7 @@ SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) { break; } } - if (dpy == NULL) { + if (dpy == nullptr) { ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id); // Just use the primary display so we have something to return dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY); diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index ed806b87f5..de78c3f355 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -148,7 +148,7 @@ protected: mBGSurfaceControl = mComposerClient->createSurface( String8("BG Interceptor Test Surface"), displayWidth, displayHeight, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_TRUE(mBGSurfaceControl != NULL); + ASSERT_TRUE(mBGSurfaceControl != nullptr); ASSERT_TRUE(mBGSurfaceControl->isValid()); mBGLayerId = getSurfaceId("BG Interceptor Test Surface"); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index ff81dc9461..ac8a2ad868 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -148,8 +148,8 @@ static void fillSurfaceRGBA8(const sp& sc, uint8_t r, uint8_t g, bool unlock = true) { ANativeWindow_Buffer outBuffer; sp s = sc->getSurface(); - ASSERT_TRUE(s != NULL); - ASSERT_EQ(NO_ERROR, s->lock(&outBuffer, NULL)); + ASSERT_TRUE(s != nullptr); + ASSERT_EQ(NO_ERROR, s->lock(&outBuffer, nullptr)); uint8_t* img = reinterpret_cast(outBuffer.bits); for (int y = 0; y < outBuffer.height; y++) { for (int x = 0; x < outBuffer.width; x++) { @@ -279,7 +279,7 @@ public: private: sp mOutBuffer; - uint8_t* mPixels = NULL; + uint8_t* mPixels = nullptr; }; class LayerTransactionTest : public ::testing::Test { @@ -1483,14 +1483,14 @@ protected: mBGSurfaceControl = mComposerClient->createSurface(String8("BG Test Surface"), displayWidth, displayHeight, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_TRUE(mBGSurfaceControl != NULL); + ASSERT_TRUE(mBGSurfaceControl != nullptr); ASSERT_TRUE(mBGSurfaceControl->isValid()); fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195); // Foreground surface mFGSurfaceControl = mComposerClient->createSurface(String8("FG Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_TRUE(mFGSurfaceControl != NULL); + ASSERT_TRUE(mFGSurfaceControl != nullptr); ASSERT_TRUE(mFGSurfaceControl->isValid()); fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); @@ -1498,7 +1498,7 @@ protected: // Synchronization surface mSyncSurfaceControl = mComposerClient->createSurface(String8("Sync Test Surface"), 1, 1, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_TRUE(mSyncSurfaceControl != NULL); + ASSERT_TRUE(mSyncSurfaceControl != nullptr); ASSERT_TRUE(mSyncSurfaceControl->isValid()); fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); @@ -2018,7 +2018,7 @@ TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { mNewComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - ASSERT_TRUE(mChildNewClient != NULL); + ASSERT_TRUE(mChildNewClient != nullptr); ASSERT_TRUE(mChildNewClient->isValid()); fillSurfaceRGBA8(mChildNewClient, 200, 200, 200); @@ -2210,7 +2210,7 @@ TEST_F(ChildLayerTest, ReparentToNoParent) { TEST_F(ChildLayerTest, ReparentFromNoParent) { sp newSurface = mComposerClient->createSurface(String8("New Surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_TRUE(newSurface != NULL); + ASSERT_TRUE(newSurface != nullptr); ASSERT_TRUE(newSurface->isValid()); fillSurfaceRGBA8(newSurface, 63, 195, 63); -- cgit v1.2.3-59-g8ed1b From 347200f079e004495aa46d6e1d5c1dec2632bbc6 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 14 Dec 2017 17:00:15 -0800 Subject: Create processDisplayChangesLocked This simply extracts the code in handleTransactionLocked for the eDisplayTransactionNeeded case into its own function. There were no changes other than a quick clang-format of the extracted function. Bug: 38464421 Test: Builds Change-Id: Id84f5b990fb6818db1f8b0c37ac02bf3caa26002 --- services/surfaceflinger/SurfaceFlinger.cpp | 299 ++++++++++++++--------------- services/surfaceflinger/SurfaceFlinger.h | 1 + 2 files changed, 145 insertions(+), 155 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e96726529b..a180606d6a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2112,6 +2112,149 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // here the transaction has been committed } +void SurfaceFlinger::processDisplayChangesLocked() { + // here we take advantage of Vector's copy-on-write semantics to + // improve performance by skipping the transaction entirely when + // know that the lists are identical + const KeyedVector, DisplayDeviceState>& curr(mCurrentState.displays); + const KeyedVector, DisplayDeviceState>& draw(mDrawingState.displays); + if (!curr.isIdenticalTo(draw)) { + mVisibleRegionsDirty = true; + const size_t cc = curr.size(); + size_t dc = draw.size(); + + // find the displays that were removed + // (ie: in drawing state but not in current state) + // also handle displays that changed + // (ie: displays that are in both lists) + for (size_t i = 0; i < dc;) { + const ssize_t j = curr.indexOfKey(draw.keyAt(i)); + if (j < 0) { + // in drawing state but not in current state + if (!draw[i].isMainDisplay()) { + // Call makeCurrent() on the primary display so we can + // be sure that nothing associated with this display + // is current. + const sp defaultDisplay(getDefaultDisplayDeviceLocked()); + defaultDisplay->makeCurrent(); + sp hw(getDisplayDeviceLocked(draw.keyAt(i))); + if (hw != nullptr) hw->disconnect(getHwComposer()); + if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) + mEventThread->onHotplugReceived(draw[i].type, false); + mDisplays.removeItem(draw.keyAt(i)); + } else { + ALOGW("trying to remove the main display"); + } + } else { + // this display is in both lists. see if something changed. + const DisplayDeviceState& state(curr[j]); + const wp& display(curr.keyAt(j)); + const sp state_binder = IInterface::asBinder(state.surface); + const sp draw_binder = IInterface::asBinder(draw[i].surface); + if (state_binder != draw_binder) { + // changing the surface is like destroying and + // recreating the DisplayDevice, so we just remove it + // from the drawing state, so that it get re-added + // below. + sp hw(getDisplayDeviceLocked(display)); + if (hw != nullptr) hw->disconnect(getHwComposer()); + mDisplays.removeItem(display); + mDrawingState.displays.removeItemsAt(i); + dc--; + // at this point we must loop to the next item + continue; + } + + const sp disp(getDisplayDeviceLocked(display)); + if (disp != nullptr) { + if (state.layerStack != draw[i].layerStack) { + disp->setLayerStack(state.layerStack); + } + if ((state.orientation != draw[i].orientation) || + (state.viewport != draw[i].viewport) || (state.frame != draw[i].frame)) { + disp->setProjection(state.orientation, state.viewport, state.frame); + } + if (state.width != draw[i].width || state.height != draw[i].height) { + disp->setDisplaySize(state.width, state.height); + } + } + } + ++i; + } + + // find displays that were added + // (ie: in current state but not in drawing state) + for (size_t i = 0; i < cc; i++) { + if (draw.indexOfKey(curr.keyAt(i)) < 0) { + const DisplayDeviceState& state(curr[i]); + + sp dispSurface; + sp producer; + sp bqProducer; + sp bqConsumer; + BufferQueue::createBufferQueue(&bqProducer, &bqConsumer); + + int32_t hwcId = -1; + if (state.isVirtualDisplay()) { + // Virtual displays without a surface are dormant: + // they have external state (layer stack, projection, + // etc.) but no internal state (i.e. a DisplayDevice). + if (state.surface != nullptr) { + // Allow VR composer to use virtual displays. + if (mUseHwcVirtualDisplays || getBE().mHwc->isUsingVrComposer()) { + int width = 0; + int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width); + ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status); + int height = 0; + status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height); + ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status); + int intFormat = 0; + status = state.surface->query(NATIVE_WINDOW_FORMAT, &intFormat); + ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status); + auto format = static_cast(intFormat); + + getBE().mHwc->allocateVirtualDisplay(width, height, &format, &hwcId); + } + + // TODO: Plumb requested format back up to consumer + + sp vds = + new VirtualDisplaySurface(*getBE().mHwc, hwcId, state.surface, + bqProducer, bqConsumer, + state.displayName); + + dispSurface = vds; + producer = vds; + } + } else { + ALOGE_IF(state.surface != nullptr, + "adding a supported display, but rendering " + "surface is provided (%p), ignoring it", + state.surface.get()); + + hwcId = state.type; + dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer); + producer = bqProducer; + } + + const wp& display(curr.keyAt(i)); + if (dispSurface != nullptr) { + sp hw = + new DisplayDevice(this, state.type, hwcId, state.isSecure, display, + dispSurface, producer, hasWideColorDisplay); + hw->setLayerStack(state.layerStack); + hw->setProjection(state.orientation, state.viewport, state.frame); + hw->setDisplayName(state.displayName); + mDisplays.add(display, hw); + if (!state.isVirtualDisplay()) { + mEventThread->onHotplugReceived(state.type, true); + } + } + } + } + } +} + void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) { // Notify all layers of available frames @@ -2140,161 +2283,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) */ if (transactionFlags & eDisplayTransactionNeeded) { - // here we take advantage of Vector's copy-on-write semantics to - // improve performance by skipping the transaction entirely when - // know that the lists are identical - const KeyedVector< wp, DisplayDeviceState>& curr(mCurrentState.displays); - const KeyedVector< wp, DisplayDeviceState>& draw(mDrawingState.displays); - if (!curr.isIdenticalTo(draw)) { - mVisibleRegionsDirty = true; - const size_t cc = curr.size(); - size_t dc = draw.size(); - - // find the displays that were removed - // (ie: in drawing state but not in current state) - // also handle displays that changed - // (ie: displays that are in both lists) - for (size_t i=0 ; i defaultDisplay(getDefaultDisplayDeviceLocked()); - defaultDisplay->makeCurrent(); - sp hw(getDisplayDeviceLocked(draw.keyAt(i))); - if (hw != nullptr) - hw->disconnect(getHwComposer()); - if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) - mEventThread->onHotplugReceived(draw[i].type, false); - mDisplays.removeItem(draw.keyAt(i)); - } else { - ALOGW("trying to remove the main display"); - } - } else { - // this display is in both lists. see if something changed. - const DisplayDeviceState& state(curr[j]); - const wp& display(curr.keyAt(j)); - const sp state_binder = IInterface::asBinder(state.surface); - const sp draw_binder = IInterface::asBinder(draw[i].surface); - if (state_binder != draw_binder) { - // changing the surface is like destroying and - // recreating the DisplayDevice, so we just remove it - // from the drawing state, so that it get re-added - // below. - sp hw(getDisplayDeviceLocked(display)); - if (hw != nullptr) - hw->disconnect(getHwComposer()); - mDisplays.removeItem(display); - mDrawingState.displays.removeItemsAt(i); - dc--; - // at this point we must loop to the next item - continue; - } - - const sp disp(getDisplayDeviceLocked(display)); - if (disp != nullptr) { - if (state.layerStack != draw[i].layerStack) { - disp->setLayerStack(state.layerStack); - } - if ((state.orientation != draw[i].orientation) - || (state.viewport != draw[i].viewport) - || (state.frame != draw[i].frame)) - { - disp->setProjection(state.orientation, - state.viewport, state.frame); - } - if (state.width != draw[i].width || state.height != draw[i].height) { - disp->setDisplaySize(state.width, state.height); - } - } - } - ++i; - } - - // find displays that were added - // (ie: in current state but not in drawing state) - for (size_t i=0 ; i dispSurface; - sp producer; - sp bqProducer; - sp bqConsumer; - BufferQueue::createBufferQueue(&bqProducer, &bqConsumer); - - int32_t hwcId = -1; - if (state.isVirtualDisplay()) { - // Virtual displays without a surface are dormant: - // they have external state (layer stack, projection, - // etc.) but no internal state (i.e. a DisplayDevice). - if (state.surface != nullptr) { - - // Allow VR composer to use virtual displays. - if (mUseHwcVirtualDisplays || getBE().mHwc->isUsingVrComposer()) { - int width = 0; - int status = state.surface->query( - NATIVE_WINDOW_WIDTH, &width); - ALOGE_IF(status != NO_ERROR, - "Unable to query width (%d)", status); - int height = 0; - status = state.surface->query( - NATIVE_WINDOW_HEIGHT, &height); - ALOGE_IF(status != NO_ERROR, - "Unable to query height (%d)", status); - int intFormat = 0; - status = state.surface->query( - NATIVE_WINDOW_FORMAT, &intFormat); - ALOGE_IF(status != NO_ERROR, - "Unable to query format (%d)", status); - auto format = static_cast( - intFormat); - - getBE().mHwc->allocateVirtualDisplay(width, height, &format, - &hwcId); - } - - // TODO: Plumb requested format back up to consumer - - sp vds = - new VirtualDisplaySurface(*getBE().mHwc, - hwcId, state.surface, bqProducer, - bqConsumer, state.displayName); - - dispSurface = vds; - producer = vds; - } - } else { - ALOGE_IF(state.surface != nullptr, - "adding a supported display, but rendering " - "surface is provided (%p), ignoring it", - state.surface.get()); - - hwcId = state.type; - dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer); - producer = bqProducer; - } - - const wp& display(curr.keyAt(i)); - if (dispSurface != nullptr) { - sp hw = - new DisplayDevice(this, state.type, hwcId, state.isSecure, display, - dispSurface, producer, hasWideColorDisplay); - hw->setLayerStack(state.layerStack); - hw->setProjection(state.orientation, - state.viewport, state.frame); - hw->setDisplayName(state.displayName); - mDisplays.add(display, hw); - if (!state.isVirtualDisplay()) { - mEventThread->onHotplugReceived(state.type, true); - } - } - } - } - } + processDisplayChangesLocked(); } if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8030fbdc41..e5364c4f3f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -637,6 +637,7 @@ private: /* ------------------------------------------------------------------------ * Display management */ + void processDisplayChangesLocked(); /* ------------------------------------------------------------------------ * VSync -- cgit v1.2.3-59-g8ed1b From ba04e6237fb6ae1aede76b543028da101412b11d Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 14 Dec 2017 17:11:26 -0800 Subject: Move hotplug processing to the main thread Queue up all hotplug events for processing in the main thread, as part of a display transaction (eDisplayTransactionNeeded). This is needed so that everything done for each individual hotplug disconnect or connect is done at the same time, such as creating and destroying the corresponding DisplayDevice. This fixes an issue with a hotplug disconnect event followed by an immediate connect event for the same display not being handled properly. Bug: 38464421 Test: Immediate disconnect/connect handled correctly. Change-Id: I96266db8b02ffd6ad9eb4897d6c8510657775991 --- services/surfaceflinger/SurfaceFlinger.cpp | 71 ++++++++++++++++++------------ services/surfaceflinger/SurfaceFlinger.h | 9 ++++ 2 files changed, 53 insertions(+), 27 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a180606d6a..1e0b67df67 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -618,6 +618,10 @@ void SurfaceFlinger::init() { "Starting with vr flinger active is not currently supported."); getBE().mHwc.reset(new HWComposer(getBE().mHwcServiceName)); getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId); + // Process any initial hotplug and resulting display changes. + processDisplayHotplugEventsLocked(); + LOG_ALWAYS_FATAL_IF(!getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY), + "Registered composer callback but didn't create the default primary display"); if (useVrFlinger) { auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) { @@ -1321,39 +1325,20 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, "connected" : "disconnected", primaryDisplay ? "primary" : "external"); + // Ignore events that do not have the right sequenceId. + if (sequenceId != getBE().mComposerSequenceId) { + return; + } + // 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); + ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); - if (primaryDisplay) { - getBE().mHwc->onHotplug(display, connection); - if (!mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY].get()) { - createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY); - } - createDefaultDisplayDevice(); - } else { - if (sequenceId != getBE().mComposerSequenceId) { - return; - } - if (getBE().mHwc->isUsingVrComposer()) { - ALOGE("External displays are not supported by the vr hardware composer."); - return; - } - getBE().mHwc->onHotplug(display, connection); - auto type = DisplayDevice::DISPLAY_EXTERNAL; - if (connection == HWC2::Connection::Connected) { - createBuiltinDisplayLocked(type); - } else { - mCurrentState.displays.removeItem(mBuiltinDisplays[type]); - mBuiltinDisplays[type].clear(); - } - setTransactionFlags(eDisplayTransactionNeeded); + mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection, primaryDisplay}); - // Defer EventThread notification until SF has updated mDisplays. - } + setTransactionFlags(eDisplayTransactionNeeded); } void SurfaceFlinger::onRefreshReceived(int sequenceId, @@ -2112,6 +2097,35 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // here the transaction has been committed } +void SurfaceFlinger::processDisplayHotplugEventsLocked() { + for (const auto& event : mPendingHotplugEvents) { + DisplayDevice::DisplayType displayType = event.isPrimaryDisplay ? + DisplayDevice::DISPLAY_PRIMARY : DisplayDevice::DISPLAY_EXTERNAL; + + if (getBE().mHwc->isUsingVrComposer() && displayType == DisplayDevice::DISPLAY_EXTERNAL) { + ALOGE("External displays are not supported by the vr hardware composer."); + continue; + } + + getBE().mHwc->onHotplug(event.display, event.connection); + + if (event.connection == HWC2::Connection::Connected) { + createBuiltinDisplayLocked(displayType); + } else { + mCurrentState.displays.removeItem(mBuiltinDisplays[displayType]); + mBuiltinDisplays[displayType].clear(); + } + + if (displayType == DisplayDevice::DISPLAY_PRIMARY) { + createDefaultDisplayDevice(); + } + + processDisplayChangesLocked(); + } + + mPendingHotplugEvents.clear(); +} + void SurfaceFlinger::processDisplayChangesLocked() { // here we take advantage of Vector's copy-on-write semantics to // improve performance by skipping the transaction entirely when @@ -2253,6 +2267,8 @@ void SurfaceFlinger::processDisplayChangesLocked() { } } } + + mDrawingState.displays = mCurrentState.displays; } void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) @@ -2284,6 +2300,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (transactionFlags & eDisplayTransactionNeeded) { processDisplayChangesLocked(); + processDisplayHotplugEventsLocked(); } if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e5364c4f3f..77977aa93b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -638,6 +638,7 @@ private: * Display management */ void processDisplayChangesLocked(); + void processDisplayHotplugEventsLocked(); /* ------------------------------------------------------------------------ * VSync @@ -739,6 +740,14 @@ private: sp mPreviousPresentFence = Fence::NO_FENCE; bool mHadClientComposition = false; + struct HotplugEvent { + hwc2_display_t display; + HWC2::Connection connection = HWC2::Connection::Invalid; + bool isPrimaryDisplay; + }; + // protected by mStateLock + std::vector mPendingHotplugEvents; + // this may only be written from the main thread with mStateLock held // it may be read from other threads with mStateLock held DefaultKeyedVector< wp, sp > mDisplays; -- cgit v1.2.3-59-g8ed1b From fcd86617fb5cbbad3463c828211868859de23329 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 14 Dec 2017 17:15:36 -0800 Subject: Eliminate duplicate device creation code On startup, SurfaceFlinger used a special code path to set up the primary display. This removes the code, as all display event processing is done on initialization, so the normal DisplayDevice creation path is used. This also resolves some differences between the two code paths so the primary display is set up the same way. Bug: 38464421 Test: Settings app is navigable. Change-Id: Icef8ee6c2ddd26604a33f06fb45ec0a743d82a29 --- services/surfaceflinger/DisplayDevice.cpp | 14 ---- services/surfaceflinger/SurfaceFlinger.cpp | 118 +++++++++++++---------------- services/surfaceflinger/SurfaceFlinger.h | 10 +-- 3 files changed, 56 insertions(+), 86 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 9772f9a1be..a6634873ae 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -127,20 +127,6 @@ DisplayDevice::DisplayDevice( mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; - // Name the display. The name will be replaced shortly if the display - // was created with createDisplay(). - switch (mType) { - case DISPLAY_PRIMARY: - mDisplayName = "Built-in Screen"; - break; - case DISPLAY_EXTERNAL: - mDisplayName = "HDMI Screen"; - break; - default: - mDisplayName = "Virtual Screen"; // e.g. Overlay #n - break; - } - // initialize the display orientation transform. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1e0b67df67..707a0dec1c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -368,17 +368,6 @@ void SurfaceFlinger::destroyDisplay(const sp& display) { setTransactionFlags(eDisplayTransactionNeeded); } -void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) { - ALOGV("createBuiltinDisplayLocked(%d)", type); - ALOGW_IF(mBuiltinDisplays[type], - "Overwriting display token for display type %d", type); - mBuiltinDisplays[type] = new BBinder(); - // All non-virtual displays are currently considered secure. - DisplayDeviceState info(type, true); - mCurrentState.displays.add(mBuiltinDisplays[type], info); - mInterceptor.saveDisplayCreation(info); -} - sp SurfaceFlinger::getBuiltInDisplay(int32_t id) { if (uint32_t(id) >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id); @@ -623,6 +612,10 @@ void SurfaceFlinger::init() { LOG_ALWAYS_FATAL_IF(!getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY), "Registered composer callback but didn't create the default primary display"); + // make the default display GLContext current so that we can create textures + // when creating Layers (which may happens before we render something) + getDefaultDisplayDeviceLocked()->makeCurrent(); + if (useVrFlinger) { auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) { // This callback is called from the vr flinger dispatch thread. We @@ -1270,52 +1263,6 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { *compositorTiming = getBE().mCompositorTiming; } -void SurfaceFlinger::createDefaultDisplayDevice() { - const DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_PRIMARY; - wp token = mBuiltinDisplays[type]; - - // All non-virtual displays are currently considered secure. - const bool isSecure = true; - - sp producer; - sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer); - - sp fbs = new FramebufferSurface(*getBE().mHwc, type, consumer); - - bool hasWideColorModes = false; - std::vector modes = getHwComposer().getColorModes(type); - for (android_color_mode_t colorMode : modes) { - switch (colorMode) { - case HAL_COLOR_MODE_DISPLAY_P3: - case HAL_COLOR_MODE_ADOBE_RGB: - case HAL_COLOR_MODE_DCI_P3: - hasWideColorModes = true; - break; - default: - break; - } - } - bool useWideColorMode = hasWideColorModes && hasWideColorDisplay && !mForceNativeColorMode; - sp hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure, - token, fbs, producer, useWideColorMode); - mDisplays.add(token, hw); - android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; - if (useWideColorMode) { - defaultColorMode = HAL_COLOR_MODE_SRGB; - } - setActiveColorModeInternal(hw, defaultColorMode); - hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN); - - // 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)); - - // make the GLContext current so that we can create textures when creating - // Layers (which may happens before we render something) - hw->makeCurrent(); -} - void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t display, HWC2::Connection connection, bool primaryDisplay) { @@ -2110,14 +2057,26 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { getBE().mHwc->onHotplug(event.display, event.connection); if (event.connection == HWC2::Connection::Connected) { - createBuiltinDisplayLocked(displayType); + ALOGV("Creating built in display %d", displayType); + ALOGW_IF(mBuiltinDisplays[displayType], + "Overwriting display token for display type %d", displayType); + mBuiltinDisplays[displayType] = new BBinder(); + // All non-virtual displays are currently considered secure. + DisplayDeviceState info(displayType, true); + info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ? + "Built-in Screen" : "External Screen"; + mCurrentState.displays.add(mBuiltinDisplays[displayType], info); + mInterceptor.saveDisplayCreation(info); } else { - mCurrentState.displays.removeItem(mBuiltinDisplays[displayType]); - mBuiltinDisplays[displayType].clear(); - } + ALOGV("Removing built in display %d", displayType); - if (displayType == DisplayDevice::DISPLAY_PRIMARY) { - createDefaultDisplayDevice(); + ssize_t idx = mCurrentState.displays.indexOfKey(mBuiltinDisplays[displayType]); + if (idx >= 0) { + const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx)); + mInterceptor.saveDisplayDeletion(info.displayId); + mCurrentState.displays.removeItemsAt(idx); + } + mBuiltinDisplays[displayType].clear(); } processDisplayChangesLocked(); @@ -2252,10 +2211,41 @@ void SurfaceFlinger::processDisplayChangesLocked() { } const wp& display(curr.keyAt(i)); + if (dispSurface != nullptr) { + bool useWideColorMode = hasWideColorDisplay; + if (state.isMainDisplay()) { + bool hasWideColorModes = false; + std::vector modes = + getHwComposer().getColorModes(state.type); + for (android_color_mode_t colorMode : modes) { + switch (colorMode) { + case HAL_COLOR_MODE_DISPLAY_P3: + case HAL_COLOR_MODE_ADOBE_RGB: + case HAL_COLOR_MODE_DCI_P3: + hasWideColorModes = true; + break; + default: + break; + } + } + useWideColorMode = hasWideColorModes && hasWideColorDisplay && + !mForceNativeColorMode; + } + sp hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, - dispSurface, producer, hasWideColorDisplay); + dispSurface, producer, useWideColorMode); + + if (state.isMainDisplay()) { + android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; + if (useWideColorMode) { + defaultColorMode = HAL_COLOR_MODE_SRGB; + } + setActiveColorModeInternal(hw, defaultColorMode); + hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN); + } + hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); hw->setDisplayName(state.displayName); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 77977aa93b..921bb45363 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -142,14 +142,14 @@ public: std::unique_ptr mRenderEngine; EGLContext mEGLContext; EGLDisplay mEGLDisplay; - + FenceTimeline mGlCompositionDoneTimeline; FenceTimeline mDisplayTimeline; // protected by mCompositorTimingLock; mutable std::mutex mCompositorTimingLock; CompositorTiming mCompositorTiming; - + // Only accessed from the main thread. struct CompositePresentTime { nsecs_t composite { -1 }; @@ -547,10 +547,6 @@ private: // called when starting, or restarting after system_server death void initializeDisplays(); - // Create an IBinder for a builtin display and add it to current state - void createBuiltinDisplayLocked(DisplayDevice::DisplayType type); - - sp getDisplayDevice(const wp& dpy) const { Mutex::Autolock _l(mStateLock); return getDisplayDeviceLocked(dpy); @@ -575,8 +571,6 @@ private: return getDisplayDeviceLocked(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]); } - void createDefaultDisplayDevice(); - int32_t getDisplayType(const sp& display) { if (!display.get()) return NAME_NOT_FOUND; for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) { -- cgit v1.2.3-59-g8ed1b From 715a2c13e6a010143761c1822ce7c4975921aa0b Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 14 Dec 2017 17:18:08 -0800 Subject: Determine displayType in SurfaceFlinger This change eliminates an assumption that the first hotplug connect event is for the primary display, and all other events are for the external display. Bug: 38464421 Test: Boots, settings app navigable Change-Id: I753deb9a4e99a7b225ab89562c7acf4ce284dbf5 --- services/surfaceflinger/DisplayHardware/HWC2.cpp | 20 +-------- services/surfaceflinger/DisplayHardware/HWC2.h | 3 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 27 ++++++------ .../surfaceflinger/DisplayHardware/HWComposer.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 49 ++++++++++++++++------ services/surfaceflinger/SurfaceFlinger.h | 6 +-- 6 files changed, 57 insertions(+), 50 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index affe505f27..070b691502 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -52,24 +52,13 @@ namespace { class ComposerCallbackBridge : public Hwc2::IComposerCallback { public: ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId) - : mCallback(callback), mSequenceId(sequenceId), - mHasPrimaryDisplay(false) {} + : mCallback(callback), mSequenceId(sequenceId) {} Return onHotplug(Hwc2::Display display, IComposerCallback::Connection conn) override { HWC2::Connection connection = static_cast(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); - } + mCallback->onHotplugReceived(mSequenceId, display, connection); return Void(); } @@ -85,12 +74,9 @@ public: return Void(); } - bool HasPrimaryDisplay() { return mHasPrimaryDisplay; } - private: ComposerCallback* mCallback; int32_t mSequenceId; - bool mHasPrimaryDisplay; }; } // namespace anonymous @@ -117,8 +103,6 @@ void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) { sp 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 diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index a15c6d940c..7b98b3e11d 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -65,8 +65,7 @@ class Layer; class ComposerCallback { public: virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display, - Connection connection, - bool primaryDisplay) = 0; + Connection connection) = 0; virtual void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) = 0; virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display, diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index c0f8f96478..1677b07c4d 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -119,23 +119,22 @@ void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) { } } -void HWComposer::onHotplug(hwc2_display_t displayId, +void HWComposer::onHotplug(hwc2_display_t displayId, int32_t displayType, HWC2::Connection connection) { - ALOGV("hotplug: %" PRIu64 ", %s", displayId, + if (displayType >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) { + ALOGE("Invalid display type of %d", displayType); + return; + } + + ALOGV("hotplug: %" PRIu64 ", %s %s", displayId, + displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external", to_string(connection).c_str()); mHwcDevice->onHotplug(displayId, connection); - if (!mDisplayData[0].hwcDisplay) { - ALOGE_IF(connection != HWC2::Connection::Connected, "Assumed primary" - " display would be connected"); - mDisplayData[0].hwcDisplay = mHwcDevice->getDisplayById(displayId); - mHwcDisplaySlots[displayId] = 0; - } else { - // Disconnect is handled through HWComposer::disconnectDisplay via - // SurfaceFlinger's onHotplugReceived callback handling - if (connection == HWC2::Connection::Connected) { - mDisplayData[1].hwcDisplay = mHwcDevice->getDisplayById(displayId); - mHwcDisplaySlots[displayId] = 1; - } + // Disconnect is handled through HWComposer::disconnectDisplay via + // SurfaceFlinger's onHotplugReceived callback handling + if (connection == HWC2::Connection::Connected) { + mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(displayId); + mHwcDisplaySlots[displayId] = displayType; } } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 74b3a38b6a..ee0a7255e2 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -136,7 +136,7 @@ public: // 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 onHotplug(hwc2_display_t displayId, int32_t displayType, HWC2::Connection connection); void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 707a0dec1c..3145ac359a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1263,14 +1263,10 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { *compositorTiming = getBE().mCompositorTiming; } -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"); +void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t display, + HWC2::Connection connection) { + ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s)", sequenceId, display, + connection == HWC2::Connection::Connected ? "connected" : "disconnected"); // Ignore events that do not have the right sequenceId. if (sequenceId != getBE().mComposerSequenceId) { @@ -1283,7 +1279,7 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, // acquire it here. ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); - mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection, primaryDisplay}); + mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection}); setTransactionFlags(eDisplayTransactionNeeded); } @@ -2044,17 +2040,46 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // here the transaction has been committed } +DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display, + HWC2::Connection connection) const { + // Figure out whether the event is for the primary display or an + // external display by matching the Hwc display id against one for a + // connected display. If we did not find a match, we then check what + // displays are not already connected to determine the type. If we don't + // have a connected primary display, we assume the new display is meant to + // be the primary display, and then if we don't have an external display, + // we assume it is that. + const auto primaryDisplayId = + getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY); + const auto externalDisplayId = + getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_EXTERNAL); + if (primaryDisplayId && primaryDisplayId == display) { + return DisplayDevice::DISPLAY_PRIMARY; + } else if (externalDisplayId && externalDisplayId == display) { + return DisplayDevice::DISPLAY_EXTERNAL; + } else if (connection == HWC2::Connection::Connected && !primaryDisplayId) { + return DisplayDevice::DISPLAY_PRIMARY; + } else if (connection == HWC2::Connection::Connected && !externalDisplayId) { + return DisplayDevice::DISPLAY_EXTERNAL; + } + + return DisplayDevice::DISPLAY_ID_INVALID; +} + void SurfaceFlinger::processDisplayHotplugEventsLocked() { for (const auto& event : mPendingHotplugEvents) { - DisplayDevice::DisplayType displayType = event.isPrimaryDisplay ? - DisplayDevice::DISPLAY_PRIMARY : DisplayDevice::DISPLAY_EXTERNAL; + auto displayType = determineDisplayType(event.display, event.connection); + if (displayType == DisplayDevice::DISPLAY_ID_INVALID) { + ALOGW("Unable to determine the display type for display %" PRIu64, event.display); + continue; + } if (getBE().mHwc->isUsingVrComposer() && displayType == DisplayDevice::DISPLAY_EXTERNAL) { ALOGE("External displays are not supported by the vr hardware composer."); continue; } - getBE().mHwc->onHotplug(event.display, event.connection); + getBE().mHwc->onHotplug(event.display, displayType, event.connection); if (event.connection == HWC2::Connection::Connected) { ALOGV("Creating built in display %d", displayType); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 921bb45363..a18be9bdda 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -417,8 +417,7 @@ private: 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; + HWC2::Connection connection) override; void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override; /* ------------------------------------------------------------------------ @@ -631,6 +630,8 @@ private: /* ------------------------------------------------------------------------ * Display management */ + DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display, + HWC2::Connection connection) const; void processDisplayChangesLocked(); void processDisplayHotplugEventsLocked(); @@ -737,7 +738,6 @@ private: struct HotplugEvent { hwc2_display_t display; HWC2::Connection connection = HWC2::Connection::Invalid; - bool isPrimaryDisplay; }; // protected by mStateLock std::vector mPendingHotplugEvents; -- cgit v1.2.3-59-g8ed1b From 2ae2b3bd5bfbacc3b52f222441bfbbeb9bd54dc7 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 14 Dec 2017 17:18:17 -0800 Subject: Allow a primary display disconnect This patch forwards the primary display disconnect event to the Framework, and otherwise ensures that SurfaceFlinger does not crash while there is no primary display. Note that the Framework does not yet accept this change. In particular the ActivityManager ActivityStackSupervisor code promptly asserts that one cannot remove the primary display. With this assertion disabled, the framework does not crash (surprisingly). And if the Framework subsequently receives a primary display connect event, it does not seem to do anything useful -- the display remains in a default off state, and no layer stack/viewport/etc is set on it. Bug: 38464421 Test: Works (with workarounds as noted) on a Chromebook Test: Added Unit test passes on Pixel 1 XL Change-Id: Ia11439030efdc53bc17474b71a0ffb3d3085bb49 --- .../DisplayHardware/FramebufferSurface.cpp | 4 + .../DisplayHardware/FramebufferSurface.h | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 54 ++++---- .../tests/fakehwc/FakeComposerClient.cpp | 6 + .../tests/fakehwc/FakeComposerClient.h | 1 + .../tests/fakehwc/SFFakeHwc_test.cpp | 154 +++++++++++++++++++-- 6 files changed, 181 insertions(+), 42 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 8b5d4c974b..4faba3b77a 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -76,6 +76,10 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp, SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1); } +void FramebufferSurface::resizeBuffers(const uint32_t width, const uint32_t height) { + mConsumer->setDefaultBufferSize(width, height); +} + status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) { return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index eaa54553ed..ed756c49a1 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -46,9 +46,7 @@ public: virtual void onFrameCommitted(); virtual void dumpAsString(String8& result) const; - // Cannot resize a buffers in a FramebufferSurface. Only works with virtual - // displays. - virtual void resizeBuffers(const uint32_t /*w*/, const uint32_t /*h*/) { }; + virtual void resizeBuffers(const uint32_t width, const uint32_t height); virtual const sp& getClientTargetAcquireFence() const override; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3145ac359a..bfa239d8c8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -798,7 +798,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, // TODO: this needs to go away (currently needed only by webkit) sp hw(getDefaultDisplayDeviceLocked()); - info.orientation = hw->getOrientation(); + info.orientation = hw ? hw->getOrientation() : 0; } else { // TODO: where should this value come from? static const int TV_DENSITY = 213; @@ -1596,7 +1596,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) getBE().mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr glCompositionDoneFenceTime; - if (getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) { + if (hw && getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) { glCompositionDoneFenceTime = std::make_shared(hw->getClientTargetAcquireFence()); getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime); @@ -1641,7 +1641,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } if (!hasSyncFramework) { - if (hw->isDisplayOn()) { + if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && hw->isDisplayOn()) { enableHardwareVsync(); } } @@ -1652,7 +1652,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) if (presentFenceTime->isValid()) { mAnimFrameTracker.setActualPresentFence( std::move(presentFenceTime)); - } else { + } else if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. nsecs_t presentTime = @@ -1662,7 +1662,8 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) mAnimFrameTracker.advanceFrame(); } - if (hw->getPowerMode() == HWC_POWER_MODE_OFF) { + if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && + hw->getPowerMode() == HWC_POWER_MODE_OFF) { return; } @@ -2005,9 +2006,11 @@ void SurfaceFlinger::postFramebuffer() mDebugInSwapBuffers = 0; // |mStateLock| not needed as we are on the main thread - uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount(); - if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { - logFrameStats(); + if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) { + uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount(); + if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { + logFrameStats(); + } } } @@ -2129,20 +2132,16 @@ void SurfaceFlinger::processDisplayChangesLocked() { const ssize_t j = curr.indexOfKey(draw.keyAt(i)); if (j < 0) { // in drawing state but not in current state - if (!draw[i].isMainDisplay()) { - // Call makeCurrent() on the primary display so we can - // be sure that nothing associated with this display - // is current. - const sp defaultDisplay(getDefaultDisplayDeviceLocked()); - defaultDisplay->makeCurrent(); - sp hw(getDisplayDeviceLocked(draw.keyAt(i))); - if (hw != nullptr) hw->disconnect(getHwComposer()); - if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) - mEventThread->onHotplugReceived(draw[i].type, false); - mDisplays.removeItem(draw.keyAt(i)); - } else { - ALOGW("trying to remove the main display"); - } + // Call makeCurrent() on the primary display so we can + // be sure that nothing associated with this display + // is current. + const sp defaultDisplay(getDefaultDisplayDeviceLocked()); + if (defaultDisplay != nullptr) defaultDisplay->makeCurrent(); + sp hw(getDisplayDeviceLocked(draw.keyAt(i))); + if (hw != nullptr) hw->disconnect(getHwComposer()); + if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) + mEventThread->onHotplugReceived(draw[i].type, false); + mDisplays.removeItem(draw.keyAt(i)); } else { // this display is in both lists. see if something changed. const DisplayDeviceState& state(curr[j]); @@ -2377,6 +2376,9 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } layer->updateTransformHint(disp); } + if (disp != nullptr) { + layer->updateTransformHint(disp); + } first = false; }); @@ -3912,9 +3914,11 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, getBE().mRenderEngine->dump(result); - hw->undefinedRegion.dump(result, "undefinedRegion"); - result.appendFormat(" orientation=%d, isDisplayOn=%d\n", - hw->getOrientation(), hw->isDisplayOn()); + if (hw) { + hw->undefinedRegion.dump(result, "undefinedRegion"); + result.appendFormat(" orientation=%d, isDisplayOn=%d\n", + hw->getOrientation(), hw->isDisplayOn()); + } result.appendFormat( " last eglSwapBuffers() time: %f us\n" " last transaction time : %f us\n" diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp index cb22932fbf..e16e7ec4d6 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp @@ -181,6 +181,12 @@ void FakeComposerClient::hotplugDisplay(Display display, IComposerCallback::Conn } } +void FakeComposerClient::refreshDisplay(Display display) { + if (mCallbacksOn) { + mClient->onRefresh(display); + } +} + uint32_t FakeComposerClient::getMaxVirtualDisplayCount() { ALOGV("getMaxVirtualDisplayCount"); return 1; diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h index de8cffdba6..cef7f5bc99 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h @@ -142,6 +142,7 @@ public: Layer getLayer(size_t index) const; void hotplugDisplay(Display display, IComposerCallback::Connection state); + void refreshDisplay(Display display); private: LayerImpl& getLayerImpl(Layer handle); diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 8a97ea4a4b..18738325f8 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -22,25 +22,22 @@ #include "FakeComposerService.h" #include "FakeComposerUtils.h" +#include #include #include #include #include #include -#include - -#include - -#include - #include - -#include - +#include +#include #include - +#include #include +#include +#include +#include #include #include @@ -142,13 +139,22 @@ public: }; protected: + static int processDisplayEvents(int fd, int events, void* data); + void SetUp() override; void TearDown() override; + void waitForDisplayTransaction(); + bool waitForHotplugEvent(uint32_t id, bool connected); + sp mFakeService; sp mComposerClient; MockComposerClient* mMockComposer; + + std::unique_ptr mReceiver; + sp mLooper;; + std::deque mReceivedDisplayEvents; }; void DisplayTest::SetUp() { @@ -188,9 +194,16 @@ void DisplayTest::SetUp() { mComposerClient = new SurfaceComposerClient; ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); + + mReceiver.reset(new DisplayEventReceiver()); + mLooper = new Looper(false); + mLooper->addFd(mReceiver->getFd(), 0, ALOOPER_EVENT_INPUT, processDisplayEvents, this); } void DisplayTest::TearDown() { + mLooper = nullptr; + mReceiver = nullptr; + mComposerClient->dispose(); mComposerClient = nullptr; @@ -204,6 +217,55 @@ void DisplayTest::TearDown() { mMockComposer = nullptr; } + +int DisplayTest::processDisplayEvents(int /*fd*/, int /*events*/, void* data) { + auto self = static_cast(data); + + ssize_t n; + DisplayEventReceiver::Event buffer[1]; + + while ((n = self->mReceiver->getEvents(buffer, 1)) > 0) { + for (int i=0 ; imReceivedDisplayEvents.push_back(buffer[i]); + } + } + ALOGD_IF(n < 0, "Error reading events (%s)\n", strerror(-n)); + return 1; +} + +void DisplayTest::waitForDisplayTransaction() { + // Both a refresh and a vsync event are needed to apply pending display + // transactions. + mMockComposer->refreshDisplay(EXTERNAL_DISPLAY); + mMockComposer->runVSyncAndWait(); + + // Extra vsync and wait to avoid a 10% flake due to a race. + mMockComposer->runVSyncAndWait(); +} + +bool DisplayTest::waitForHotplugEvent(uint32_t id, bool connected) { + int waitCount = 20; + while (waitCount--) { + while (!mReceivedDisplayEvents.empty()) { + auto event = mReceivedDisplayEvents.front(); + mReceivedDisplayEvents.pop_front(); + + ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, + "event hotplug: id %d, connected %d\t", event.header.id, + event.hotplug.connected); + + if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG && + event.header.id == id && event.hotplug.connected == connected) { + return true; + } + } + + mLooper->pollOnce(1); + } + + return false; +} + TEST_F(DisplayTest, Hotplug) { ALOGD("DisplayTest::Hotplug"); @@ -215,7 +277,7 @@ TEST_F(DisplayTest, Hotplug) { EXPECT_CALL(*mMockComposer, getDisplayAttribute(EXTERNAL_DISPLAY, 1, _, _)) .Times(2 * 3) .WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake)); - // ... and then special handling for dimensions. Specifying this + // ... and then special handling for dimensions. Specifying these // rules later means that gmock will try them first, i.e., // ordering of width/height vs. the default implementation for // other queries is significant. @@ -229,11 +291,12 @@ TEST_F(DisplayTest, Hotplug) { .Times(2) .WillRepeatedly(DoAll(SetArgPointee<3>(200), Return(Error::NONE))); - // TODO: Width and height queries are not actually called. Display - // info returns dimensions 0x0 in display info. Why? - mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::CONNECTED); + waitForDisplayTransaction(); + + EXPECT_TRUE(waitForHotplugEvent(ISurfaceComposer::eDisplayIdHdmi, true)); + { sp display( SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdHdmi)); @@ -264,6 +327,11 @@ TEST_F(DisplayTest, Hotplug) { mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::CONNECTED); + waitForDisplayTransaction(); + + EXPECT_TRUE(waitForHotplugEvent(ISurfaceComposer::eDisplayIdHdmi, false)); + EXPECT_TRUE(waitForHotplugEvent(ISurfaceComposer::eDisplayIdHdmi, true)); + { sp display( SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdHdmi)); @@ -290,6 +358,64 @@ TEST_F(DisplayTest, Hotplug) { mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::DISCONNECTED); } +TEST_F(DisplayTest, HotplugPrimaryDisplay) { + ALOGD("DisplayTest::HotplugPrimaryDisplay"); + + mMockComposer->hotplugDisplay(PRIMARY_DISPLAY, IComposerCallback::Connection::DISCONNECTED); + + waitForDisplayTransaction(); + + EXPECT_TRUE(waitForHotplugEvent(ISurfaceComposer::eDisplayIdMain, false)); + + { + sp display( + SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); + DisplayInfo info; + auto result = SurfaceComposerClient::getDisplayInfo(display, &info); + EXPECT_NE(NO_ERROR, result); + } + + mMockComposer->clearFrames(); + + EXPECT_CALL(*mMockComposer, getDisplayType(PRIMARY_DISPLAY, _)) + .Times(2) + .WillRepeatedly(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL), + Return(Error::NONE))); + // The attribute queries will get done twice. This is for defaults + EXPECT_CALL(*mMockComposer, getDisplayAttribute(PRIMARY_DISPLAY, 1, _, _)) + .Times(2 * 3) + .WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake)); + // ... and then special handling for dimensions. Specifying these + // rules later means that gmock will try them first, i.e., + // ordering of width/height vs. the default implementation for + // other queries is significant. + EXPECT_CALL(*mMockComposer, + getDisplayAttribute(PRIMARY_DISPLAY, 1, IComposerClient::Attribute::WIDTH, _)) + .Times(2) + .WillRepeatedly(DoAll(SetArgPointee<3>(400), Return(Error::NONE))); + + EXPECT_CALL(*mMockComposer, + getDisplayAttribute(PRIMARY_DISPLAY, 1, IComposerClient::Attribute::HEIGHT, _)) + .Times(2) + .WillRepeatedly(DoAll(SetArgPointee<3>(200), Return(Error::NONE))); + + mMockComposer->hotplugDisplay(PRIMARY_DISPLAY, IComposerCallback::Connection::CONNECTED); + + waitForDisplayTransaction(); + + EXPECT_TRUE(waitForHotplugEvent(ISurfaceComposer::eDisplayIdMain, true)); + + { + sp display( + SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); + DisplayInfo info; + auto result = SurfaceComposerClient::getDisplayInfo(display, &info); + EXPECT_EQ(NO_ERROR, result); + ASSERT_EQ(400u, info.w); + ASSERT_EQ(200u, info.h); + } +} + //////////////////////////////////////////////// class TransactionTest : public ::testing::Test { -- cgit v1.2.3-59-g8ed1b From c520831fb7ea03e9d515add9b2d96d423b3b6093 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Mon, 8 Jan 2018 17:59:02 -0800 Subject: Use wide color modes with external displays A prior code cleanup made it obvious that wide color modes were only being used for the primary display. This patch allows external displays to use wide color modes, and adds a requested TODO to update a variable name. Bug: None Test: Builds Change-Id: Iec262e51674a2a2f7fcfc9177c7bfbf0b1a860e3 --- services/surfaceflinger/SurfaceFlinger.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index bfa239d8c8..f21a691e31 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -136,6 +136,7 @@ uint64_t SurfaceFlinger::maxVirtualDisplaySize; bool SurfaceFlinger::hasSyncFramework; bool SurfaceFlinger::useVrFlinger; int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers; +// TODO(courtneygo): Rename hasWideColorDisplay to clarify its actual meaning. bool SurfaceFlinger::hasWideColorDisplay; @@ -2238,7 +2239,7 @@ void SurfaceFlinger::processDisplayChangesLocked() { if (dispSurface != nullptr) { bool useWideColorMode = hasWideColorDisplay; - if (state.isMainDisplay()) { + if (!mForceNativeColorMode) { bool hasWideColorModes = false; std::vector modes = getHwComposer().getColorModes(state.type); @@ -2253,26 +2254,23 @@ void SurfaceFlinger::processDisplayChangesLocked() { break; } } - useWideColorMode = hasWideColorModes && hasWideColorDisplay && - !mForceNativeColorMode; + useWideColorMode = hasWideColorModes && hasWideColorDisplay; } sp hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, dispSurface, producer, useWideColorMode); - if (state.isMainDisplay()) { - android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; - if (useWideColorMode) { - defaultColorMode = HAL_COLOR_MODE_SRGB; - } - setActiveColorModeInternal(hw, defaultColorMode); - hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN); + android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; + if (useWideColorMode) { + defaultColorMode = HAL_COLOR_MODE_SRGB; } - + setActiveColorModeInternal(hw, defaultColorMode); + hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); hw->setDisplayName(state.displayName); + mDisplays.add(display, hw); if (!state.isVirtualDisplay()) { mEventThread->onHotplugReceived(state.type, true); -- cgit v1.2.3-59-g8ed1b From e5f4f694f11ad1e8a9bb3b1b9579a175435c7c19 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Fri, 12 Jan 2018 13:12:28 -0800 Subject: SurfaceFlinger: Optimize region calculation for invisible layers. This CL causes the computeVisibleRegions codepath to escape earlier for a given layer when it is found that it's visible region is empty. All the juggling in the later part of the function can end up being quite expensive even when it's no-op. It seems this is largely due to allocation of storage space for temporary Region variables. In particular I found that without this CL Walleye was uncapable of staying in 60fps mode when there were 100 fully occluded layers and 1 visible layer. With this CL we're able to stay in 60FPS. We are running in to this issue in some practical cases where we can have a few dozen parent layers with no buffer adding a lot of time to computeVisibleRegion. Since they have no mActiveBuffer they will bail early from isVisible and benefit from this change. Test: Manual. Existing tests pass. Change-Id: I7dd39f8641649a3cc38b4ed017ffe9b6eefcf224 --- services/surfaceflinger/Layer.cpp | 6 ++++++ services/surfaceflinger/Layer.h | 5 +++++ services/surfaceflinger/SurfaceFlinger.cpp | 5 +++++ 3 files changed, 16 insertions(+) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 63f6781f02..33f0796ae0 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -871,6 +871,12 @@ void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparen this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; } +void Layer::clearVisibilityRegions() { + visibleRegion.clear(); + visibleNonTransparentRegion.clear(); + coveredRegion.clear(); +} + // ---------------------------------------------------------------------------- // transaction // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index e44ccf8d57..c63399e876 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -434,6 +434,11 @@ public: */ void setVisibleNonTransparentRegion(const Region& visibleNonTransparentRegion); + /* + * Clear the visible, covered, and non-transparent regions. + */ + void clearVisibilityRegions(); + /* * latchBuffer - called each time the screen is redrawn and returns whether * the visible regions need to be recomputed (this is a fairly heavy diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e96726529b..3b9a6cfab8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2513,6 +2513,11 @@ void SurfaceFlinger::computeVisibleRegions(const sp& displa } } + if (visibleRegion.isEmpty()) { + layer->clearVisibilityRegions(); + return; + } + // Clip the covered region to the visible region coveredRegion = aboveCoveredLayers.intersect(visibleRegion); -- cgit v1.2.3-59-g8ed1b From 5b15ef66927507f01c6ec19ed39b04dfc549a111 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Wed, 17 Jan 2018 18:31:39 +0100 Subject: Enable IMG_context_priority depending on availability The config value from the config store can still be used to override it. Test: Enable gpu completion tracing, observe how SF preempts other GPU drawing Bug: 64674361 Change-Id: Id2f6f11019c2e6cae078fb9e64e3d9d72e42533c --- .../surfaceflinger/RenderEngine/GLExtensions.cpp | 3 +++ .../surfaceflinger/RenderEngine/GLExtensions.h | 2 ++ .../surfaceflinger/RenderEngine/RenderEngine.cpp | 24 ++++++++++++++++++---- .../surfaceflinger/RenderEngine/RenderEngine.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 5 ----- services/surfaceflinger/SurfaceFlinger.h | 3 --- 6 files changed, 27 insertions(+), 12 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/GLExtensions.cpp index e6e4df1a6f..dc09a376bb 100644 --- a/services/surfaceflinger/RenderEngine/GLExtensions.cpp +++ b/services/surfaceflinger/RenderEngine/GLExtensions.cpp @@ -106,6 +106,9 @@ void GLExtensions::initWithEGLStrings(char const* eglVersion, char const* eglExt if (hasEGLExtension("EGL_EXT_protected_content")) { mHasProtectedContent = true; } + if (hasEGLExtension("EGL_IMG_context_priority")) { + mHasContextPriority = true; + } } char const* GLExtensions::getEGLVersion() const { diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.h b/services/surfaceflinger/RenderEngine/GLExtensions.h index 81078e0455..0d8c10b0ac 100644 --- a/services/surfaceflinger/RenderEngine/GLExtensions.h +++ b/services/surfaceflinger/RenderEngine/GLExtensions.h @@ -41,6 +41,7 @@ class GLExtensions : public Singleton { bool mHasWaitSync = false; bool mHasImageCrop = false; bool mHasProtectedContent = false; + bool mHasContextPriority = false; String8 mVendor; String8 mRenderer; @@ -67,6 +68,7 @@ public: bool hasWaitSync() const { return mHasWaitSync; } bool hasImageCrop() const { return mHasImageCrop; } bool hasProtectedContent() const { return mHasProtectedContent; } + bool hasContextPriority() const { return mHasContextPriority; } void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version, GLubyte const* extensions); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 179b79003c..22016edd85 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -27,6 +27,12 @@ #include #include +#include +#include + +using namespace android::hardware::configstore; +using namespace android::hardware::configstore::V1_0; + extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); // --------------------------------------------------------------------------- @@ -70,13 +76,11 @@ std::unique_ptr RenderEngine::create(int hwcFormat, uint32_t featu contextAttributes.reserve(6); contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION); contextAttributes.push_back(contextClientVersion); -#ifdef EGL_IMG_context_priority - if (SurfaceFlinger::useContextPriority) { + bool useContextPriority = overrideUseContextPriorityFromConfig(extensions.hasContextPriority()); + if (useContextPriority) { contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG); contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG); } -#endif - contextAttributes.push_back(EGL_NONE); contextAttributes.push_back(EGL_NONE); EGLContext ctxt = eglCreateContext(display, config, nullptr, contextAttributes.data()); @@ -131,6 +135,18 @@ std::unique_ptr RenderEngine::create(int hwcFormat, uint32_t featu return engine; } +bool RenderEngine::overrideUseContextPriorityFromConfig(bool useContextPriority) { + OptionalBool ret; + ISurfaceFlingerConfigs::getService()->useContextPriority([&ret](OptionalBool b) { + ret = b; + }); + if (ret.specified) { + return ret.value; + } else { + return useContextPriority; + } +} + RenderEngine::RenderEngine() : mEGLDisplay(EGL_NO_DISPLAY), mEGLConfig(nullptr), mEGLContext(EGL_NO_CONTEXT) {} diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index f8869197b1..737b1dd789 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -66,6 +66,8 @@ class RenderEngine { uint32_t* status) = 0; virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0; + static bool overrideUseContextPriorityFromConfig(bool useContextPriority); + protected: RenderEngine(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b03519e0f3..27b9e93467 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -129,7 +129,6 @@ const String16 sDump("android.permission.DUMP"); // --------------------------------------------------------------------------- int64_t SurfaceFlinger::vsyncPhaseOffsetNs; int64_t SurfaceFlinger::sfVsyncPhaseOffsetNs; -bool SurfaceFlinger::useContextPriority; int64_t SurfaceFlinger::dispSyncPresentTimeOffset; bool SurfaceFlinger::useHwcForRgbToYuv; uint64_t SurfaceFlinger::maxVirtualDisplaySize; @@ -207,9 +206,6 @@ SurfaceFlinger::SurfaceFlinger() hasSyncFramework = getBool< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasSyncFramework>(true); - useContextPriority = getBool< ISurfaceFlingerConfigs, - &ISurfaceFlingerConfigs::useContextPriority>(false); - dispSyncPresentTimeOffset = getInt64< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::presentTimeOffsetFromVSyncNs>(0); @@ -3692,7 +3688,6 @@ void SurfaceFlinger::logFrameStats() { void SurfaceFlinger::appendSfConfigString(String8& result) const { result.append(" [sf"); - result.appendFormat(" HAS_CONTEXT_PRIORITY=%d", useContextPriority); if (isLayerTripleBufferingDisabled()) result.append(" DISABLE_TRIPLE_BUFFERING"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a18be9bdda..4da0803f67 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -227,9 +227,6 @@ public: // If fences from sync Framework are supported. static bool hasSyncFramework; - // Instruct the Render Engine to use EGL_IMG_context_priority is available. - static bool useContextPriority; - // The offset in nanoseconds to use when DispSync timestamps present fence // signaling time. static int64_t dispSyncPresentTimeOffset; -- cgit v1.2.3-59-g8ed1b From 8acf5a0acc2d45d090bbc25fa8bbb07ce1076e40 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Wed, 17 Jan 2018 21:28:19 +0100 Subject: SurfaceFlinger: Do not capture rounded corners on screenshots Fixes a regression that arose because we no longer properly checked for the layerStack when traversing the layers for screenshotting. Bug: 72111097 Test: Take screenshot, verify rounded corner overlays do not appear. Change-Id: Ifc178247fe5b72376c56a0a1d347d7bd04784cae --- services/surfaceflinger/SurfaceFlinger.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f21a691e31..0fd5050c7f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4645,6 +4645,9 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp& hw, continue; } layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + if (!layer->belongsToDisplay(hw->getLayerStack(), false)) { + return; + } if (!layer->isVisible()) { return; } -- cgit v1.2.3-59-g8ed1b From 5c6e46353676b4fd647317fde28c413d8ffe3565 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 11 Jan 2018 08:54:38 -0800 Subject: surfaceflinger: always advertise HDR10 when wide color is available For HWC that already adversises HDR10 support, this has no effect. Otherwise, SurfaceFlinger will insert HDR10 into HdrCapabilities when wide color is supported. SurfaceFlinger simulates HDR10 support by switching the color mode to DISPLAY_P3 and forcing client composition for HDR10 layers. It also has a special path to treat RGBA_1010102/BT2020_PQ as Y410/BT2020_PQ in RenderEngine when the buffer is from media. Test: manual Change-Id: Ib5f18e0100f5610ee65218108bdb9843baccbe98 --- libs/gui/BufferItem.cpp | 6 +++- libs/gui/BufferQueueProducer.cpp | 1 + libs/gui/include/gui/BufferItem.h | 3 ++ services/surfaceflinger/BufferLayer.cpp | 9 ++++++ services/surfaceflinger/BufferLayerConsumer.cpp | 7 +++++ services/surfaceflinger/BufferLayerConsumer.h | 5 ++++ services/surfaceflinger/DisplayDevice.cpp | 5 +++- services/surfaceflinger/DisplayDevice.h | 4 ++- services/surfaceflinger/SurfaceFlinger.cpp | 39 ++++++++++++++++++++++--- services/surfaceflinger/SurfaceFlinger.h | 3 +- 10 files changed, 74 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp index f7409dc344..f50379b3ed 100644 --- a/libs/gui/BufferItem.cpp +++ b/libs/gui/BufferItem.cpp @@ -55,7 +55,8 @@ BufferItem::BufferItem() : mSurfaceDamage(), mAutoRefresh(false), mQueuedBuffer(true), - mIsStale(false) { + mIsStale(false), + mApi(0) { } BufferItem::~BufferItem() {} @@ -84,6 +85,7 @@ size_t BufferItem::getPodSize() const { addAligned(size, mAutoRefresh); addAligned(size, mQueuedBuffer); addAligned(size, mIsStale); + addAligned(size, mApi); return size; } @@ -177,6 +179,7 @@ status_t BufferItem::flatten( writeAligned(buffer, size, mAutoRefresh); writeAligned(buffer, size, mQueuedBuffer); writeAligned(buffer, size, mIsStale); + writeAligned(buffer, size, mApi); return NO_ERROR; } @@ -247,6 +250,7 @@ status_t BufferItem::unflatten( readAligned(buffer, size, mAutoRefresh); readAligned(buffer, size, mQueuedBuffer); readAligned(buffer, size, mIsStale); + readAligned(buffer, size, mApi); return NO_ERROR; } diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index add857c350..e583b40632 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -878,6 +878,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, item.mSurfaceDamage = surfaceDamage; item.mQueuedBuffer = true; item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh; + item.mApi = mCore->mConnectedApi; mStickyTransform = stickyTransform; diff --git a/libs/gui/include/gui/BufferItem.h b/libs/gui/include/gui/BufferItem.h index 7740b9f095..218bb424fb 100644 --- a/libs/gui/include/gui/BufferItem.h +++ b/libs/gui/include/gui/BufferItem.h @@ -127,6 +127,9 @@ class BufferItem : public Flattenable { // Indicates that this BufferItem contains a stale buffer which has already // been released by the BufferQueue. bool mIsStale; + + // Indicates the API (NATIVE_WINDOW_API_xxx) that queues the buffer. + int mApi; }; } // namespace android diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index d860f58509..ab6a559aad 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -821,8 +821,17 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */, getColor()); engine.setSourceDataSpace(mCurrentState.dataSpace); + + if (mCurrentState.dataSpace == HAL_DATASPACE_BT2020_PQ && + mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA && + getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) { + engine.setSourceY410BT2020(true); + } + engine.drawMesh(getBE().mMesh); engine.disableBlending(); + + engine.setSourceY410BT2020(false); } uint32_t BufferLayer::getProducerStickyTransform() const { diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 8f5c9c740b..4d9b43f52e 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -68,6 +68,7 @@ BufferLayerConsumer::BufferLayerConsumer(const sp& bq, R mCurrentFrameNumber(0), mCurrentTransformToDisplayInverse(false), mCurrentSurfaceDamage(), + mCurrentApi(0), mDefaultWidth(1), mDefaultHeight(1), mFilteringEnabled(true), @@ -346,6 +347,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, mCurrentFrameNumber = item.mFrameNumber; mCurrentTransformToDisplayInverse = item.mTransformToDisplayInverse; mCurrentSurfaceDamage = item.mSurfaceDamage; + mCurrentApi = item.mApi; computeCurrentTransformMatrixLocked(); @@ -469,6 +471,11 @@ const Region& BufferLayerConsumer::getSurfaceDamage() const { return mCurrentSurfaceDamage; } +int BufferLayerConsumer::getCurrentApi() const { + Mutex::Autolock lock(mMutex); + return mCurrentApi; +} + sp BufferLayerConsumer::getCurrentBuffer(int* outSlot) const { Mutex::Autolock lock(mMutex); diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index f473390ea7..a0272b3622 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -138,6 +138,9 @@ public: // must be called from SF main thread const Region& getSurfaceDamage() const; + // getCurrentApi retrieves the API which queues the current buffer. + int getCurrentApi() const; + // See GLConsumer::setDefaultBufferSize. status_t setDefaultBufferSize(uint32_t width, uint32_t height); @@ -337,6 +340,8 @@ private: // The portion of this surface that has changed since the previous frame Region mCurrentSurfaceDamage; + int mCurrentApi; + uint32_t mDefaultWidth, mDefaultHeight; // mFilteringEnabled indicates whether the transform matrix is computed for diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index d121a86ead..cf70529b53 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -76,7 +76,8 @@ DisplayDevice::DisplayDevice( const wp& displayToken, const sp& displaySurface, const sp& producer, - bool supportWideColor) + bool supportWideColor, + bool supportHdr) : lastCompositionHadVisibleLayers(false), mFlinger(flinger), mType(type), @@ -100,6 +101,8 @@ DisplayDevice::DisplayDevice( mActiveColorMode = HAL_COLOR_MODE_NATIVE; mDisplayHasWideColor = supportWideColor; + mDisplayHasHdr = supportHdr; + /* * Create our display's surface */ diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 499bf8e6a0..a4706701a8 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -78,7 +78,7 @@ public: const wp& displayToken, const sp& displaySurface, const sp& producer, - bool supportWideColor); + bool supportWideColor, bool supportHdr); // clang-format on ~DisplayDevice(); @@ -128,6 +128,7 @@ public: status_t beginFrame(bool mustRecompose) const; status_t prepareFrame(HWComposer& hwc); bool getWideColorSupport() const { return mDisplayHasWideColor; } + bool getHdrSupport() const { return mDisplayHasHdr; } void swapBuffers(HWComposer& hwc) const; @@ -235,6 +236,7 @@ private: // Initialized by SurfaceFlinger when the DisplayDevice is created. // Fed to RenderEngine during composition. bool mDisplayHasWideColor; + bool mDisplayHasHdr; }; struct DisplayDeviceState { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a91525d8d0..974a261278 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1041,7 +1041,19 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp& display, std::unique_ptr capabilities = getBE().mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId()); if (capabilities) { - std::swap(*outCapabilities, *capabilities); + if (displayDevice->getWideColorSupport() && !displayDevice->getHdrSupport()) { + // insert HDR10 as we will force client composition for HDR10 + // layers + std::vector types = capabilities->getSupportedHdrTypes(); + types.push_back(HAL_HDR_HDR10); + + *outCapabilities = HdrCapabilities(types, + capabilities->getDesiredMaxLuminance(), + capabilities->getDesiredMaxAverageLuminance(), + capabilities->getDesiredMinLuminance()); + } else { + *outCapabilities = std::move(*capabilities); + } } else { return BAD_VALUE; } @@ -1793,7 +1805,7 @@ android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) co } android_dataspace SurfaceFlinger::bestTargetDataSpace( - android_dataspace a, android_dataspace b) const { + android_dataspace a, android_dataspace b, bool hasHdr) const { // Only support sRGB and Display-P3 right now. if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) { return HAL_DATASPACE_DISPLAY_P3; @@ -1804,6 +1816,9 @@ android_dataspace SurfaceFlinger::bestTargetDataSpace( if (a == HAL_DATASPACE_V0_SCRGB || b == HAL_DATASPACE_V0_SCRGB) { return HAL_DATASPACE_DISPLAY_P3; } + if (!hasHdr && (a == HAL_DATASPACE_BT2020_PQ || b == HAL_DATASPACE_BT2020_PQ)) { + return HAL_DATASPACE_DISPLAY_P3; + } return HAL_DATASPACE_V0_SRGB; } @@ -1885,6 +1900,11 @@ void SurfaceFlinger::setUpHWComposer() { "display %zd: %d", displayId, result); } for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + if (layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ && + !displayDevice->getHdrSupport()) { + layer->forceClientComposition(hwcId); + } + if (layer->getForceClientComposition(hwcId)) { ALOGV("[%s] Requesting Client composition", layer->getName().string()); layer->setCompositionType(hwcId, HWC2::Composition::Client); @@ -1899,7 +1919,8 @@ void SurfaceFlinger::setUpHWComposer() { android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB; for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace); + newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace, + displayDevice->getHdrSupport()); ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)", layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(), layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace); @@ -2253,9 +2274,19 @@ void SurfaceFlinger::processDisplayChangesLocked() { useWideColorMode = hasWideColorModes && hasWideColorDisplay; } + bool hasHdrSupport = false; + std::unique_ptr hdrCapabilities = + getHwComposer().getHdrCapabilities(state.type); + if (hdrCapabilities) { + const std::vector types = hdrCapabilities->getSupportedHdrTypes(); + auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10); + hasHdrSupport = iter != types.cend(); + } + sp hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, - dispSurface, producer, useWideColorMode); + dispSurface, producer, useWideColorMode, + hasHdrSupport); android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; if (useWideColorMode) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 4da0803f67..1349becf13 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -607,7 +607,8 @@ private: // Given a dataSpace, returns the appropriate color_mode to use // to display that dataSpace. android_color_mode pickColorMode(android_dataspace dataSpace) const; - android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b) const; + android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b, + bool hasHdr) const; mat4 computeSaturationMatrix() const; -- cgit v1.2.3-59-g8ed1b From 8d2651e484d5090e8d067672cb82ca285b93f4a9 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 24 Jan 2018 12:18:49 -0800 Subject: surfaceflinger: support BT2020_ITU_PQ Games use BT2020_PQ while videos use BT2020_ITU_PQ usually. We can support both and treat them as the same, since the YUV->RGB conversion happens before the pixel data are uploaded to texture, or happens inside the GLES driver. The only caveat is that we treat RGBA1010102/BT2020_ITU_PQ from media specially. The hack is also updated in this change. Test: manual Change-Id: I1e4b8e0d907af5e5a95cf7fde1a7ea67a4e7da0b --- services/surfaceflinger/BufferLayer.cpp | 2 +- services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp | 3 ++- services/surfaceflinger/SurfaceFlinger.cpp | 12 +++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index ba9eaf6db2..4d4c9fcc3d 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -822,7 +822,7 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT getColor()); engine.setSourceDataSpace(mCurrentState.dataSpace); - if (mCurrentState.dataSpace == HAL_DATASPACE_BT2020_PQ && + if (mCurrentState.dataSpace == HAL_DATASPACE_BT2020_ITU_PQ && mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA && getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) { engine.setSourceY410BT2020(true); diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 323cec75b9..5133bacc2d 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -326,11 +326,12 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { if (usesWideColor()) { Description wideColorState = mState; - switch (mDataSpace) { + switch (int(mDataSpace)) { case HAL_DATASPACE_DISPLAY_P3: // input matches output break; case HAL_DATASPACE_BT2020_PQ: + case HAL_DATASPACE_BT2020_ITU_PQ: wideColorState.setColorMatrix(mState.getColorMatrix() * mBt2020ToDisplayP3); wideColorState.setInputTransferFunction(Description::TransferFunction::ST2084); wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 974a261278..d8740d973e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1816,8 +1816,13 @@ android_dataspace SurfaceFlinger::bestTargetDataSpace( if (a == HAL_DATASPACE_V0_SCRGB || b == HAL_DATASPACE_V0_SCRGB) { return HAL_DATASPACE_DISPLAY_P3; } - if (!hasHdr && (a == HAL_DATASPACE_BT2020_PQ || b == HAL_DATASPACE_BT2020_PQ)) { - return HAL_DATASPACE_DISPLAY_P3; + if (!hasHdr) { + if (a == HAL_DATASPACE_BT2020_PQ || b == HAL_DATASPACE_BT2020_PQ) { + return HAL_DATASPACE_DISPLAY_P3; + } + if (a == HAL_DATASPACE_BT2020_ITU_PQ || b == HAL_DATASPACE_BT2020_ITU_PQ) { + return HAL_DATASPACE_DISPLAY_P3; + } } return HAL_DATASPACE_V0_SRGB; @@ -1900,7 +1905,8 @@ void SurfaceFlinger::setUpHWComposer() { "display %zd: %d", displayId, result); } for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - if (layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ && + if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ || + layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) && !displayDevice->getHdrSupport()) { layer->forceClientComposition(hwcId); } -- cgit v1.2.3-59-g8ed1b From 755e319d6a656dc92bd4f2b486d8f5a44b0e7350 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 31 Jan 2018 16:46:15 -0800 Subject: SF: Cleanup EventControlThread Primarily the goal was to eliminate the use of RefBase in various forms from EventControlThread. 1) SurfaceFlinger only needs a std::unique_ptr<> and not an android::sp<> to own the created instance. 2) Convert from android::Thread to std::thread, along with using std::mutex and std::condition_variable to keep consistency. 3) The code only needs a reference to a function to call, rather than a reference to all of SurfaceFlinger. This removes an unnecessary full dependency. 4) Switch the header to #pragma once. 5) Added Clang thread annotations and enabled the corresponding warning. 6) Simplified the thread function to eliminate unnecessary locals and indentation. 7) Added proper thread shutdown handling (invoked by dtor). Bug: None Test: Verified event control thread still works on Pixel XL Change-Id: I2d5621b0cbbfb9e0f8c5831ccfc94704c95a4a55 --- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/EventControlThread.cpp | 70 +++++++++++++++----------- services/surfaceflinger/EventControlThread.h | 38 ++++++++------ services/surfaceflinger/SurfaceFlinger.cpp | 11 ++-- services/surfaceflinger/SurfaceFlinger.h | 2 +- 5 files changed, 72 insertions(+), 50 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 9f3189a39c..4ed4392028 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -4,6 +4,7 @@ cc_defaults { "-DLOG_TAG=\"SurfaceFlinger\"", "-Wall", "-Werror", + "-Wthread-safety", "-Wunused", "-Wunreachable-code", ], diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp index 6fd4cdf28e..ac54059360 100644 --- a/services/surfaceflinger/EventControlThread.cpp +++ b/services/surfaceflinger/EventControlThread.cpp @@ -14,45 +14,57 @@ * limitations under the License. */ +#include +#include +#include + +#include +#include +#include + #include "EventControlThread.h" -#include "SurfaceFlinger.h" namespace android { -EventControlThread::EventControlThread(const sp& flinger) - : mFlinger(flinger), mVsyncEnabled(false) {} +EventControlThread::EventControlThread(EventControlThread::SetVSyncEnabledFunction function) + : mSetVSyncEnabled(function) { + pthread_setname_np(mThread.native_handle(), "EventControlThread"); + + pid_t tid = pthread_gettid_np(mThread.native_handle()); + setpriority(PRIO_PROCESS, tid, ANDROID_PRIORITY_URGENT_DISPLAY); + set_sched_policy(tid, SP_FOREGROUND); +} + +EventControlThread::~EventControlThread() { + { + std::lock_guard lock(mMutex); + mKeepRunning = false; + mCondition.notify_all(); + } + mThread.join(); +} void EventControlThread::setVsyncEnabled(bool enabled) { - Mutex::Autolock lock(mMutex); + std::lock_guard lock(mMutex); mVsyncEnabled = enabled; - mCond.signal(); + mCondition.notify_all(); } -bool EventControlThread::threadLoop() { - enum class VsyncState { Unset, On, Off }; - auto currentVsyncState = VsyncState::Unset; - - while (true) { - 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; - } - } - - bool enable = requestedVsyncState == VsyncState::On; - mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable); - currentVsyncState = requestedVsyncState; - } +// Unfortunately std::unique_lock gives warnings with -Wthread-safety +void EventControlThread::threadMain() NO_THREAD_SAFETY_ANALYSIS { + auto keepRunning = true; + auto currentVsyncEnabled = false; - return false; + while (keepRunning) { + mSetVSyncEnabled(currentVsyncEnabled); + + std::unique_lock lock(mMutex); + mCondition.wait(lock, [this, currentVsyncEnabled, keepRunning]() NO_THREAD_SAFETY_ANALYSIS { + return currentVsyncEnabled != mVsyncEnabled || keepRunning != mKeepRunning; + }); + currentVsyncEnabled = mVsyncEnabled; + keepRunning = mKeepRunning; + } } } // namespace android diff --git a/services/surfaceflinger/EventControlThread.h b/services/surfaceflinger/EventControlThread.h index 1b1ef75b9d..321fb79831 100644 --- a/services/surfaceflinger/EventControlThread.h +++ b/services/surfaceflinger/EventControlThread.h @@ -14,35 +14,41 @@ * limitations under the License. */ -#ifndef ANDROID_EVENTCONTROLTHREAD_H -#define ANDROID_EVENTCONTROLTHREAD_H +#pragma once -#include +#include +#include +#include +#include +#include -#include -#include +#include namespace android { class SurfaceFlinger; -class EventControlThread: public Thread { +class EventControlThread { public: + using SetVSyncEnabledFunction = std::function; - explicit EventControlThread(const sp& flinger); - virtual ~EventControlThread() {} + explicit EventControlThread(SetVSyncEnabledFunction function); + ~EventControlThread(); void setVsyncEnabled(bool enabled); - virtual bool threadLoop(); private: - sp mFlinger; - bool mVsyncEnabled; + void threadMain(); - Mutex mMutex; - Condition mCond; -}; + std::mutex mMutex; + std::condition_variable mCondition; + + const SetVSyncEnabledFunction mSetVSyncEnabled; + bool mVsyncEnabled GUARDED_BY(mMutex) = false; + bool mKeepRunning GUARDED_BY(mMutex) = true; -} + // Must be last so that everything is initialized before the thread starts. + std::thread mThread{&EventControlThread::threadMain, this}; +}; -#endif // ANDROID_EVENTCONTROLTHREAD_H +} // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d8740d973e..70a282db17 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -636,8 +636,9 @@ void SurfaceFlinger::init() { } } - mEventControlThread = new EventControlThread(this); - mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY); + mEventControlThread = std::make_unique([this](bool enabled) { + setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); + }); // initialize our drawing state mDrawingState = mCurrentState; @@ -1101,7 +1102,8 @@ status_t SurfaceFlinger::injectVSync(nsecs_t when) { return NO_ERROR; } -status_t SurfaceFlinger::getLayerDebugInfo(std::vector* outLayers) const { +status_t SurfaceFlinger::getLayerDebugInfo(std::vector* outLayers) const + NO_THREAD_SAFETY_ANALYSIS { IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); @@ -3567,7 +3569,8 @@ void SurfaceFlinger::setPowerMode(const sp& display, int mode) { // --------------------------------------------------------------------------- -status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asProto) { +status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asProto) + NO_THREAD_SAFETY_ANALYSIS { String8 result; IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bde1a8e2be..89f3930a04 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -723,7 +723,7 @@ private: sp mSFEventThread; sp mInjectorEventThread; sp mVSyncInjector; - sp mEventControlThread; + std::unique_ptr mEventControlThread; sp mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; // Can only accessed from the main thread, these members -- cgit v1.2.3-59-g8ed1b From 46a46b317153f26e3361c9c74158fc6414bff7da Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 31 Jan 2018 19:01:18 -0800 Subject: SF: Cleanup EventThread Part 1 The cleanups in this CL are primarily about switching from android::Thread to std::thread. 1) Convert from android::Thread to std::thread, along with using std::mutex and std::condition_variable to keep consistency. 2) Switch the header to #pragma once. 3) Added Clang thread annotations and enabled the corresponding warning. 4) Added proper thread shutdown handling (invoked by dtor). Test: No issues observed on Pixel XL Bug: None Change-Id: I2ef0ad18ef75e139f70d856031991f87d187efe6 --- services/surfaceflinger/EventThread.cpp | 161 +++++++++++++++++------------ services/surfaceflinger/EventThread.h | 60 ++++++----- services/surfaceflinger/SurfaceFlinger.cpp | 17 +-- 3 files changed, 131 insertions(+), 107 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index 6b92cc8a0e..2cbc59edb4 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -16,10 +16,14 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include +#include +#include #include +#include +#include #include +#include #include #include @@ -31,105 +35,126 @@ #include "EventThread.h" #include "SurfaceFlinger.h" +using namespace std::chrono_literals; + // --------------------------------------------------------------------------- + namespace android { + // --------------------------------------------------------------------------- -EventThread::EventThread(const sp& src, SurfaceFlinger& flinger, bool interceptVSyncs) - : mVSyncSource(src), - mFlinger(flinger), - mUseSoftwareVSync(false), - mVsyncEnabled(false), - mDebugVsyncEnabled(false), - mInterceptVSyncs(interceptVSyncs) { - for (int32_t i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; i++) { - mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; - mVSyncEvent[i].header.id = 0; - mVSyncEvent[i].header.timestamp = 0; - mVSyncEvent[i].vsync.count = 0; +EventThread::EventThread(const sp& src, SurfaceFlinger& flinger, bool interceptVSyncs, + const char* threadName) + : mVSyncSource(src), mFlinger(flinger), mInterceptVSyncs(interceptVSyncs) { + for (auto& event : mVSyncEvent) { + event.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; + event.header.id = 0; + event.header.timestamp = 0; + event.vsync.count = 0; + } + + mThread = std::thread(&EventThread::threadMain, this); + + pthread_setname_np(mThread.native_handle(), threadName); + + pid_t tid = pthread_gettid_np(mThread.native_handle()); + + // Use SCHED_FIFO to minimize jitter + constexpr int EVENT_THREAD_PRIORITY = 2; + struct sched_param param = {0}; + param.sched_priority = EVENT_THREAD_PRIORITY; + if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, ¶m) != 0) { + ALOGE("Couldn't set SCHED_FIFO for EventThread"); + } + + set_sched_policy(tid, SP_FOREGROUND); +} + +EventThread::~EventThread() { + { + std::lock_guard lock(mMutex); + mKeepRunning = false; + mCondition.notify_all(); } + mThread.join(); } void EventThread::setPhaseOffset(nsecs_t phaseOffset) { - Mutex::Autolock _l(mLock); + std::lock_guard lock(mMutex); mVSyncSource->setPhaseOffset(phaseOffset); } -void EventThread::onFirstRef() { - run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); -} - sp EventThread::createEventConnection() const { return new Connection(const_cast(this)); } status_t EventThread::registerDisplayEventConnection( const sp& connection) { - Mutex::Autolock _l(mLock); + std::lock_guard lock(mMutex); mDisplayEventConnections.add(connection); - mCondition.broadcast(); + mCondition.notify_all(); return NO_ERROR; } void EventThread::removeDisplayEventConnection(const wp& connection) { - Mutex::Autolock _l(mLock); + std::lock_guard lock(mMutex); mDisplayEventConnections.remove(connection); } void EventThread::setVsyncRate(uint32_t count, const sp& connection) { if (int32_t(count) >= 0) { // server must protect against bad params - Mutex::Autolock _l(mLock); + std::lock_guard lock(mMutex); const int32_t new_count = (count == 0) ? -1 : count; if (connection->count != new_count) { connection->count = new_count; - mCondition.broadcast(); + mCondition.notify_all(); } } } void EventThread::requestNextVsync(const sp& connection) { - Mutex::Autolock _l(mLock); + std::lock_guard lock(mMutex); mFlinger.resyncWithRateLimit(); if (connection->count < 0) { connection->count = 0; - mCondition.broadcast(); + mCondition.notify_all(); } } void EventThread::onScreenReleased() { - Mutex::Autolock _l(mLock); + std::lock_guard lock(mMutex); if (!mUseSoftwareVSync) { // disable reliance on h/w vsync mUseSoftwareVSync = true; - mCondition.broadcast(); + mCondition.notify_all(); } } void EventThread::onScreenAcquired() { - Mutex::Autolock _l(mLock); + std::lock_guard lock(mMutex); if (mUseSoftwareVSync) { // resume use of h/w vsync mUseSoftwareVSync = false; - mCondition.broadcast(); + mCondition.notify_all(); } } void EventThread::onVSyncEvent(nsecs_t timestamp) { - Mutex::Autolock _l(mLock); + std::lock_guard lock(mMutex); mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[0].header.id = 0; mVSyncEvent[0].header.timestamp = timestamp; mVSyncEvent[0].vsync.count++; - mCondition.broadcast(); + mCondition.notify_all(); } void EventThread::onHotplugReceived(int type, bool connected) { ALOGE_IF(type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES, "received hotplug event for an invalid display (id=%d)", type); - Mutex::Autolock _l(mLock); + std::lock_guard lock(mMutex); if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { DisplayEventReceiver::Event event; event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG; @@ -137,46 +162,48 @@ void EventThread::onHotplugReceived(int type, bool connected) { event.header.timestamp = systemTime(); event.hotplug.connected = connected; mPendingEvents.add(event); - mCondition.broadcast(); + mCondition.notify_all(); } } -bool EventThread::threadLoop() { - DisplayEventReceiver::Event event; - Vector > signalConnections; - signalConnections = waitForEvent(&event); - - // dispatch events to listeners... - const size_t count = signalConnections.size(); - for (size_t i = 0; i < count; i++) { - const sp& conn(signalConnections[i]); - // now see if we still need to report this event - status_t err = conn->postEvent(event); - if (err == -EAGAIN || err == -EWOULDBLOCK) { - // The destination doesn't accept events anymore, it's probably - // full. For now, we just drop the events on the floor. - // FIXME: Note that some events cannot be dropped and would have - // to be re-sent later. - // Right-now we don't have the ability to do this. - ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type, - conn.get()); - } else if (err < 0) { - // handle any other error on the pipe as fatal. the only - // reasonable thing to do is to clean-up this connection. - // The most common error we'll get here is -EPIPE. - removeDisplayEventConnection(signalConnections[i]); +void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS { + std::unique_lock lock(mMutex); + while (mKeepRunning) { + DisplayEventReceiver::Event event; + Vector > signalConnections; + signalConnections = waitForEventLocked(&lock, &event); + + // dispatch events to listeners... + const size_t count = signalConnections.size(); + for (size_t i = 0; i < count; i++) { + const sp& conn(signalConnections[i]); + // now see if we still need to report this event + status_t err = conn->postEvent(event); + if (err == -EAGAIN || err == -EWOULDBLOCK) { + // The destination doesn't accept events anymore, it's probably + // full. For now, we just drop the events on the floor. + // FIXME: Note that some events cannot be dropped and would have + // to be re-sent later. + // Right-now we don't have the ability to do this. + ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type, + conn.get()); + } else if (err < 0) { + // handle any other error on the pipe as fatal. the only + // reasonable thing to do is to clean-up this connection. + // The most common error we'll get here is -EPIPE. + removeDisplayEventConnection(signalConnections[i]); + } } } - return true; } // This will return when (1) a vsync event has been received, and (2) there was // at least one connection interested in receiving it when we started waiting. -Vector > EventThread::waitForEvent(DisplayEventReceiver::Event* event) { - Mutex::Autolock _l(mLock); +Vector > EventThread::waitForEventLocked( + std::unique_lock* lock, DisplayEventReceiver::Event* event) { Vector > signalConnections; - do { + while (signalConnections.isEmpty() && mKeepRunning) { bool eventPending = false; bool waitForVSync = false; @@ -279,8 +306,8 @@ Vector > EventThread::waitForEvent(DisplayEventRecei // use a (long) timeout when waiting for h/w vsync, and // generate fake events when necessary. bool softwareSync = mUseSoftwareVSync; - nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000); - if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) { + auto timeout = softwareSync ? 16ms : 1000ms; + if (mCondition.wait_for(*lock, timeout) == std::cv_status::timeout) { if (!softwareSync) { ALOGW("Timed out waiting for hw vsync; faking it"); } @@ -296,10 +323,10 @@ Vector > EventThread::waitForEvent(DisplayEventRecei // h/w vsync should be disabled, so this will wait until we // get a new connection, or an existing connection becomes // interested in receiving vsync again. - mCondition.wait(mLock); + mCondition.wait(*lock); } } - } while (signalConnections.isEmpty()); + } // here we're guaranteed to have a timestamp and some connections to signal // (The connections might have dropped out of mDisplayEventConnections @@ -328,7 +355,7 @@ void EventThread::disableVSyncLocked() { } void EventThread::dump(String8& result) const { - Mutex::Autolock _l(mLock); + std::lock_guard lock(mMutex); result.appendFormat("VSYNC state: %s\n", mDebugVsyncEnabled ? "enabled" : "disabled"); result.appendFormat(" soft-vsync: %s\n", mUseSoftwareVSync ? "enabled" : "disabled"); result.appendFormat(" numListeners=%zu,\n events-delivered: %u\n", @@ -377,4 +404,4 @@ status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& e // --------------------------------------------------------------------------- -}; // namespace android +} // namespace android diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h index b4d718cd17..63cdb542f3 100644 --- a/services/surfaceflinger/EventThread.h +++ b/services/surfaceflinger/EventThread.h @@ -14,19 +14,23 @@ * limitations under the License. */ -#ifndef ANDROID_SURFACE_FLINGER_EVENT_THREAD_H -#define ANDROID_SURFACE_FLINGER_EVENT_THREAD_H +#pragma once #include #include +#include +#include +#include + +#include #include #include #include #include +#include #include -#include #include "DisplayDevice.h" @@ -53,7 +57,7 @@ public: virtual void setPhaseOffset(nsecs_t phaseOffset) = 0; }; -class EventThread : public Thread, private VSyncSource::Callback { +class EventThread : public virtual RefBase, private VSyncSource::Callback { class Connection : public BnDisplayEventConnection { public: explicit Connection(const sp& eventThread); @@ -75,7 +79,9 @@ class EventThread : public Thread, private VSyncSource::Callback { }; public: - EventThread(const sp& src, SurfaceFlinger& flinger, bool interceptVSyncs); + EventThread(const sp& src, SurfaceFlinger& flinger, bool interceptVSyncs, + const char* threadName); + ~EventThread(); sp createEventConnection() const; status_t registerDisplayEventConnection(const sp& connection); @@ -92,46 +98,46 @@ public: // called when receiving a hotplug event void onHotplugReceived(int type, bool connected); - Vector > waitForEvent(DisplayEventReceiver::Event* event); - void dump(String8& result) const; void setPhaseOffset(nsecs_t phaseOffset); private: - virtual bool threadLoop(); - virtual void onFirstRef(); - - virtual void onVSyncEvent(nsecs_t timestamp); + void threadMain(); + Vector> waitForEventLocked(std::unique_lock* lock, + DisplayEventReceiver::Event* event) + REQUIRES(mMutex); void removeDisplayEventConnection(const wp& connection); - void enableVSyncLocked(); - void disableVSyncLocked(); + void enableVSyncLocked() REQUIRES(mMutex); + void disableVSyncLocked() REQUIRES(mMutex); + + // Implements VSyncSource::Callback + void onVSyncEvent(nsecs_t timestamp) override; // constants - sp mVSyncSource; + sp mVSyncSource GUARDED_BY(mMutex); SurfaceFlinger& mFlinger; - mutable Mutex mLock; - mutable Condition mCondition; + std::thread mThread; + mutable std::mutex mMutex; + mutable std::condition_variable mCondition; // protected by mLock - SortedVector > mDisplayEventConnections; - Vector mPendingEvents; - DisplayEventReceiver::Event mVSyncEvent[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; - bool mUseSoftwareVSync; - bool mVsyncEnabled; + SortedVector> mDisplayEventConnections GUARDED_BY(mMutex); + Vector mPendingEvents GUARDED_BY(mMutex); + DisplayEventReceiver::Event mVSyncEvent[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES] GUARDED_BY( + mMutex); + bool mUseSoftwareVSync GUARDED_BY(mMutex) = false; + bool mVsyncEnabled GUARDED_BY(mMutex) = false; + bool mKeepRunning GUARDED_BY(mMutex) = true; // for debugging - bool mDebugVsyncEnabled; + bool mDebugVsyncEnabled GUARDED_BY(mMutex) = false; - const bool mInterceptVSyncs; + const bool mInterceptVSyncs = false; }; // --------------------------------------------------------------------------- }; // namespace android - -// --------------------------------------------------------------------------- - -#endif /* ANDROID_SURFACE_FLINGER_EVENT_THREAD_H */ diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 70a282db17..3774ab1e4c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -579,22 +579,12 @@ void SurfaceFlinger::init() { // start the EventThread sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app"); - mEventThread = new EventThread(vsyncSrc, *this, false); + mEventThread = new EventThread(vsyncSrc, *this, false, "appEventThread"); sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf"); - mSFEventThread = new EventThread(sfVsyncSrc, *this, true); + mSFEventThread = new EventThread(sfVsyncSrc, *this, true, "sfEventThread"); mEventQueue.setEventThread(mSFEventThread); - // 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, ¶m) != 0) { - ALOGE("Couldn't set SCHED_FIFO for SFEventThread"); - } - if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) { - ALOGE("Couldn't set SCHED_FIFO for EventThread"); - } - // Get a RenderEngine for the given display / config (can't fail) getBE().mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0); @@ -1074,7 +1064,8 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) { ALOGV("VSync Injections enabled"); if (mVSyncInjector.get() == nullptr) { mVSyncInjector = new InjectVSyncSource(); - mInjectorEventThread = new EventThread(mVSyncInjector, *this, false); + mInjectorEventThread = new EventThread(mVSyncInjector, *this, false, + "injEventThread"); } mEventQueue.setEventThread(mInjectorEventThread); } else { -- cgit v1.2.3-59-g8ed1b From e83f93151800f4f7999f7e0c3b727de9267a5f5f Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 1 Feb 2018 12:53:17 -0800 Subject: SF: Cleanup EventThread Part 2 De-refbase EventThread and a bunch of related classes. Convert from usign StrongPointer to std::unique_ptr to hold owned references, or bare pointers for unowned references. I did not see any need for using std::shared_ptr, or anything else, as SurfaceFlinger appeared to own all the objects, and they were created once and not really destroyed afterwards. Test: Things seem to still work on a Pixel XL Bug: None Change-Id: Ifff32118d31bc1bb51e38df695ebe5cf86d2bb6d --- services/surfaceflinger/DispSync.cpp | 16 ++++---- services/surfaceflinger/DispSync.h | 8 ++-- services/surfaceflinger/EventThread.cpp | 6 +-- services/surfaceflinger/EventThread.h | 17 ++++----- services/surfaceflinger/MessageQueue.cpp | 2 +- services/surfaceflinger/MessageQueue.h | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 59 +++++++++++++++--------------- services/surfaceflinger/SurfaceFlinger.h | 10 +++-- 8 files changed, 63 insertions(+), 59 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index b5fc365470..9e01fd0d8d 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -168,8 +168,7 @@ public: return false; } - status_t addEventListener(const char* name, nsecs_t phase, - const sp& callback) { + status_t addEventListener(const char* name, nsecs_t phase, DispSync::Callback* callback) { if (kTraceDetailedInfo) ATRACE_CALL(); Mutex::Autolock lock(mMutex); @@ -195,7 +194,7 @@ public: return NO_ERROR; } - status_t removeEventListener(const sp& callback) { + status_t removeEventListener(DispSync::Callback* callback) { if (kTraceDetailedInfo) ATRACE_CALL(); Mutex::Autolock lock(mMutex); @@ -223,11 +222,11 @@ private: const char* mName; nsecs_t mPhase; nsecs_t mLastEventTime; - sp mCallback; + DispSync::Callback* mCallback; }; struct CallbackInvocation { - sp mCallback; + DispSync::Callback* mCallback; nsecs_t mEventTime; }; @@ -388,7 +387,8 @@ void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) { // not needed because any time there is an event registered we will // turn on the HW vsync events. if (!mIgnorePresentFences && kEnableZeroPhaseTracer) { - addEventListener("ZeroPhaseTracer", 0, new ZeroPhaseTracer()); + mZeroPhaseTracer = std::make_unique(); + addEventListener("ZeroPhaseTracer", 0, mZeroPhaseTracer.get()); } } } @@ -470,7 +470,7 @@ bool DispSync::addResyncSample(nsecs_t timestamp) { void DispSync::endResync() {} -status_t DispSync::addEventListener(const char* name, nsecs_t phase, const sp& callback) { +status_t DispSync::addEventListener(const char* name, nsecs_t phase, Callback* callback) { Mutex::Autolock lock(mMutex); return mThread->addEventListener(name, phase, callback); } @@ -482,7 +482,7 @@ void DispSync::setRefreshSkipCount(int count) { updateModelLocked(); } -status_t DispSync::removeEventListener(const sp& callback) { +status_t DispSync::removeEventListener(Callback* callback) { Mutex::Autolock lock(mMutex); return mThread->removeEventListener(callback); } diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index d066d55107..9336f4dd86 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -48,7 +48,7 @@ class DispSyncThread; // needed. class DispSync { public: - class Callback : public virtual RefBase { + class Callback { public: virtual ~Callback(){}; virtual void onDispSyncEvent(nsecs_t when) = 0; @@ -106,12 +106,12 @@ public: // given phase offset from the hardware vsync events. The callback is // called from a separate thread and it should return reasonably quickly // (i.e. within a few hundred microseconds). - status_t addEventListener(const char* name, nsecs_t phase, const sp& callback); + status_t addEventListener(const char* name, nsecs_t phase, Callback* callback); // removeEventListener removes an already-registered event callback. Once // this method returns that callback will no longer be called by the // DispSync object. - status_t removeEventListener(const sp& callback); + status_t removeEventListener(Callback* callback); // computeNextRefresh computes when the next refresh is expected to begin. // The periodOffset value can be used to move forward or backward; an @@ -188,6 +188,8 @@ private: // Ignore present (retire) fences if the device doesn't have support for the // sync framework bool mIgnorePresentFences; + + std::unique_ptr mZeroPhaseTracer; }; } // namespace android diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index 2cbc59edb4..53d95e21ec 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -43,7 +43,7 @@ namespace android { // --------------------------------------------------------------------------- -EventThread::EventThread(const sp& src, SurfaceFlinger& flinger, bool interceptVSyncs, +EventThread::EventThread(VSyncSource* src, SurfaceFlinger& flinger, bool interceptVSyncs, const char* threadName) : mVSyncSource(src), mFlinger(flinger), mInterceptVSyncs(interceptVSyncs) { for (auto& event : mVSyncEvent) { @@ -339,7 +339,7 @@ void EventThread::enableVSyncLocked() { // never enable h/w VSYNC when screen is off if (!mVsyncEnabled) { mVsyncEnabled = true; - mVSyncSource->setCallback(static_cast(this)); + mVSyncSource->setCallback(this); mVSyncSource->setVSyncEnabled(true); } } @@ -370,7 +370,7 @@ void EventThread::dump(String8& result) const { // --------------------------------------------------------------------------- -EventThread::Connection::Connection(const sp& eventThread) +EventThread::Connection::Connection(EventThread* eventThread) : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {} EventThread::Connection::~Connection() { diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h index 63cdb542f3..9ae8fb25b0 100644 --- a/services/surfaceflinger/EventThread.h +++ b/services/surfaceflinger/EventThread.h @@ -29,7 +29,6 @@ #include #include -#include #include #include "DisplayDevice.h" @@ -43,9 +42,9 @@ class String8; // --------------------------------------------------------------------------- -class VSyncSource : public virtual RefBase { +class VSyncSource { public: - class Callback : public virtual RefBase { + class Callback { public: virtual ~Callback() {} virtual void onVSyncEvent(nsecs_t when) = 0; @@ -53,14 +52,14 @@ public: virtual ~VSyncSource() {} virtual void setVSyncEnabled(bool enable) = 0; - virtual void setCallback(const sp& callback) = 0; + virtual void setCallback(Callback* callback) = 0; virtual void setPhaseOffset(nsecs_t phaseOffset) = 0; }; -class EventThread : public virtual RefBase, private VSyncSource::Callback { +class EventThread : private VSyncSource::Callback { class Connection : public BnDisplayEventConnection { public: - explicit Connection(const sp& eventThread); + explicit Connection(EventThread* eventThread); status_t postEvent(const DisplayEventReceiver::Event& event); // count >= 1 : continuous event. count is the vsync rate @@ -74,12 +73,12 @@ class EventThread : public virtual RefBase, private VSyncSource::Callback { status_t stealReceiveChannel(gui::BitTube* outChannel) override; status_t setVsyncRate(uint32_t count) override; void requestNextVsync() override; // asynchronous - sp const mEventThread; + EventThread* const mEventThread; gui::BitTube mChannel; }; public: - EventThread(const sp& src, SurfaceFlinger& flinger, bool interceptVSyncs, + EventThread(VSyncSource* src, SurfaceFlinger& flinger, bool interceptVSyncs, const char* threadName); ~EventThread(); @@ -116,7 +115,7 @@ private: void onVSyncEvent(nsecs_t timestamp) override; // constants - sp mVSyncSource GUARDED_BY(mMutex); + VSyncSource* mVSyncSource GUARDED_BY(mMutex) = nullptr; SurfaceFlinger& mFlinger; std::thread mThread; diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp index c9c398969c..5a6ff4dd98 100644 --- a/services/surfaceflinger/MessageQueue.cpp +++ b/services/surfaceflinger/MessageQueue.cpp @@ -82,7 +82,7 @@ void MessageQueue::init(const sp& flinger) { mHandler = new Handler(*this); } -void MessageQueue::setEventThread(const sp& eventThread) { +void MessageQueue::setEventThread(EventThread* eventThread) { if (mEventThread == eventThread) { return; } diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h index fe1bf081b8..dcfc716524 100644 --- a/services/surfaceflinger/MessageQueue.h +++ b/services/surfaceflinger/MessageQueue.h @@ -93,7 +93,7 @@ class MessageQueue { sp mFlinger; sp mLooper; - sp mEventThread; + EventThread* mEventThread; sp mEvents; gui::BitTube mEventTube; sp mHandler; @@ -110,7 +110,7 @@ public: MessageQueue(); ~MessageQueue(); void init(const sp& flinger); - void setEventThread(const sp& events); + void setEventThread(EventThread* events); void waitMessage(); status_t postMessage(const sp& message, nsecs_t reltime = 0); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3774ab1e4c..1054c32043 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -424,7 +424,7 @@ void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture)); } -class DispSyncSource : public VSyncSource, private DispSync::Callback { +class DispSyncSource final : public VSyncSource, private DispSync::Callback { public: DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* name) : @@ -435,14 +435,13 @@ public: mVsyncEventLabel(String8::format("VSYNC-%s", name)), mDispSync(dispSync), mCallbackMutex(), - mCallback(), mVsyncMutex(), mPhaseOffset(phaseOffset), mEnabled(false) {} - virtual ~DispSyncSource() {} + ~DispSyncSource() override = default; - virtual void setVSyncEnabled(bool enable) { + void setVSyncEnabled(bool enable) override { Mutex::Autolock lock(mVsyncMutex); if (enable) { status_t err = mDispSync->addEventListener(mName, mPhaseOffset, @@ -464,12 +463,12 @@ public: mEnabled = enable; } - virtual void setCallback(const sp& callback) { + void setCallback(VSyncSource::Callback* callback) override{ Mutex::Autolock lock(mCallbackMutex); mCallback = callback; } - virtual void setPhaseOffset(nsecs_t phaseOffset) { + void setPhaseOffset(nsecs_t phaseOffset) override { Mutex::Autolock lock(mVsyncMutex); // Normalize phaseOffset to [0, period) @@ -506,7 +505,7 @@ public: private: virtual void onDispSyncEvent(nsecs_t when) { - sp callback; + VSyncSource::Callback* callback; { Mutex::Autolock lock(mCallbackMutex); callback = mCallback; @@ -533,37 +532,36 @@ private: DispSync* mDispSync; Mutex mCallbackMutex; // Protects the following - sp mCallback; + VSyncSource::Callback* mCallback = nullptr; Mutex mVsyncMutex; // Protects the following nsecs_t mPhaseOffset; bool mEnabled; }; -class InjectVSyncSource : public VSyncSource { +class InjectVSyncSource final : public VSyncSource { public: - InjectVSyncSource() {} + InjectVSyncSource() = default; + ~InjectVSyncSource() override = default; - virtual ~InjectVSyncSource() {} - - virtual void setCallback(const sp& callback) { + void setCallback(VSyncSource::Callback* callback) override { std::lock_guard lock(mCallbackMutex); mCallback = callback; } - virtual void onInjectSyncEvent(nsecs_t when) { + void onInjectSyncEvent(nsecs_t when) { std::lock_guard lock(mCallbackMutex); if (mCallback) { mCallback->onVSyncEvent(when); } } - virtual void setVSyncEnabled(bool) {} - virtual void setPhaseOffset(nsecs_t) {} + void setVSyncEnabled(bool) override {} + void setPhaseOffset(nsecs_t) override {} private: std::mutex mCallbackMutex; // Protects the following - sp mCallback; + VSyncSource::Callback* mCallback = nullptr; }; // Do not call property_set on main thread which will be blocked by init @@ -577,13 +575,16 @@ void SurfaceFlinger::init() { Mutex::Autolock _l(mStateLock); // start the EventThread - sp vsyncSrc = - new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app"); - mEventThread = new EventThread(vsyncSrc, *this, false, "appEventThread"); - sp sfVsyncSrc = - new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf"); - mSFEventThread = new EventThread(sfVsyncSrc, *this, true, "sfEventThread"); - mEventQueue.setEventThread(mSFEventThread); + + mEventThreadSource = std::make_unique( + &mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app"); + mEventThread = std::make_unique( + mEventThreadSource.get(), *this, false, "sfEventThread"); + mSfEventThreadSource = std::make_unique( + &mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf"); + mSFEventThread = std::make_unique( + mSfEventThreadSource.get(), *this, true, "appEventThread"); + mEventQueue.setEventThread(mSFEventThread.get()); // Get a RenderEngine for the given display / config (can't fail) getBE().mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, @@ -1063,14 +1064,14 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) { if (enable) { ALOGV("VSync Injections enabled"); if (mVSyncInjector.get() == nullptr) { - mVSyncInjector = new InjectVSyncSource(); - mInjectorEventThread = new EventThread(mVSyncInjector, *this, false, - "injEventThread"); + mVSyncInjector = std::make_unique(); + mInjectorEventThread = std::make_unique( + mVSyncInjector.get(), *this, false, "injEvThread"); } - mEventQueue.setEventThread(mInjectorEventThread); + mEventQueue.setEventThread(mInjectorEventThread.get()); } else { ALOGV("VSync Injections disabled"); - mEventQueue.setEventThread(mSFEventThread); + mEventQueue.setEventThread(mSFEventThread.get()); } mInjectVSyncs = enable; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 89f3930a04..19dd059e97 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -719,10 +719,12 @@ private: // constant members (no synchronization needed for access) nsecs_t mBootTime; bool mGpuToCpuSupported; - sp mEventThread; - sp mSFEventThread; - sp mInjectorEventThread; - sp mVSyncInjector; + std::unique_ptr mEventThread; + std::unique_ptr mSFEventThread; + std::unique_ptr mInjectorEventThread; + std::unique_ptr mEventThreadSource; + std::unique_ptr mSfEventThreadSource; + std::unique_ptr mVSyncInjector; std::unique_ptr mEventControlThread; sp mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; -- cgit v1.2.3-59-g8ed1b From a822d52f1a7f651bf1056f4b99e7b8dd214c2ebb Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 20 Dec 2017 16:42:57 -0800 Subject: SF: Separate Hwc2::Composer into interface and impl This makes the android::Hwc2::Composer substitutable. In this case the intent is to allow a mock::Composer GMock class to be defined. Hwc2::Composer now is a pure interface class. Hwc2::impl::Composer is the normal implementation. Also included is another minor change to allow HWC2::Device to be constructed with a Hwc2::Composer (interface) pointer instead of a service name. This means that now SurfaceFlinger itself constructs the Hwc2::impl::Composer using the service name, rather than passing it down a call chain. Test: Code builds Bug: None Change-Id: Ic79f645cee40c534651b9c7b70f05497d98e51dc --- libs/vr/libvrflinger/hardware_composer.cpp | 2 +- .../surfaceflinger/DisplayHardware/ComposerHal.cpp | 8 + .../surfaceflinger/DisplayHardware/ComposerHal.h | 246 +++++++++++++++------ services/surfaceflinger/DisplayHardware/HWC2.cpp | 7 +- services/surfaceflinger/DisplayHardware/HWC2.h | 6 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 21 +- .../surfaceflinger/DisplayHardware/HWComposer.h | 19 +- services/surfaceflinger/SurfaceFlinger.cpp | 6 +- 8 files changed, 204 insertions(+), 111 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp index d655d69fef..be8a721526 100644 --- a/libs/vr/libvrflinger/hardware_composer.cpp +++ b/libs/vr/libvrflinger/hardware_composer.cpp @@ -244,7 +244,7 @@ void HardwareComposer::OnPostThreadResumed() { // Standalones only create the composer client once and then use SetPowerMode // to control the screen on pause/resume. if (!is_standalone_device_ || !composer_) { - composer_.reset(new Hwc2::Composer("default")); + composer_.reset(new Hwc2::impl::Composer("default")); composer_callback_ = new ComposerCallback; composer_->registerCallback(composer_callback_); LOG_ALWAYS_FATAL_IF(!composer_callback_->HasDisplayId(), diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index c707e3cc65..03b714f958 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -31,6 +31,8 @@ using hardware::hidl_handle; namespace Hwc2 { +Composer::~Composer() = default; + namespace { class BufferHandle { @@ -103,6 +105,8 @@ Error unwrapRet(Return& ret) } // anonymous namespace +namespace impl { + Composer::CommandWriter::CommandWriter(uint32_t initialMaxSize) : CommandWriterBase(initialMaxSize) {} @@ -186,6 +190,8 @@ Composer::Composer(const std::string& serviceName) } } +Composer::~Composer() = default; + std::vector Composer::getCapabilities() { std::vector capabilities; @@ -1118,6 +1124,8 @@ void CommandReader::takePresentOrValidateStage(Display display, uint32_t* state) *state = data.presentOrValidateState; } +} // namespace impl + } // namespace Hwc2 } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 3d9993e38f..4372362a4b 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -58,6 +58,118 @@ using android::hardware::MQDescriptorSync; using android::hardware::hidl_vec; using android::hardware::hidl_handle; +class Composer { +public: + virtual ~Composer() = 0; + + virtual std::vector getCapabilities() = 0; + virtual std::string dumpDebugInfo() = 0; + + virtual void registerCallback(const sp& callback) = 0; + + // 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. + virtual bool isRemote() = 0; + + // Reset all pending commands in the command buffer. Useful if you want to + // skip a frame but have already queued some commands. + virtual void resetCommands() = 0; + + // Explicitly flush all pending commands in the command buffer. + virtual Error executeCommands() = 0; + + virtual uint32_t getMaxVirtualDisplayCount() = 0; + virtual bool isUsingVrComposer() const = 0; + virtual Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, + Display* outDisplay) = 0; + virtual Error destroyVirtualDisplay(Display display) = 0; + + virtual Error acceptDisplayChanges(Display display) = 0; + + virtual Error createLayer(Display display, Layer* outLayer) = 0; + virtual Error destroyLayer(Display display, Layer layer) = 0; + + virtual Error getActiveConfig(Display display, Config* outConfig) = 0; + virtual Error getChangedCompositionTypes( + Display display, std::vector* outLayers, + std::vector* outTypes) = 0; + virtual Error getColorModes(Display display, std::vector* outModes) = 0; + virtual Error getDisplayAttribute(Display display, Config config, + IComposerClient::Attribute attribute, int32_t* outValue) = 0; + virtual Error getDisplayConfigs(Display display, std::vector* outConfigs) = 0; + virtual Error getDisplayName(Display display, std::string* outName) = 0; + + virtual Error getDisplayRequests(Display display, uint32_t* outDisplayRequestMask, + std::vector* outLayers, + std::vector* outLayerRequestMasks) = 0; + + virtual Error getDisplayType(Display display, IComposerClient::DisplayType* outType) = 0; + virtual Error getDozeSupport(Display display, bool* outSupport) = 0; + virtual Error getHdrCapabilities(Display display, std::vector* outTypes, + float* outMaxLuminance, float* outMaxAverageLuminance, + float* outMinLuminance) = 0; + + virtual Error getReleaseFences(Display display, std::vector* outLayers, + std::vector* outReleaseFences) = 0; + + virtual Error presentDisplay(Display display, int* outPresentFence) = 0; + + virtual Error setActiveConfig(Display display, Config config) = 0; + + /* + * The composer caches client targets internally. When target is nullptr, + * the composer uses slot to look up the client target from its cache. + * When target is not nullptr, the cache is updated with the new target. + */ + virtual Error setClientTarget(Display display, uint32_t slot, const sp& target, + int acquireFence, Dataspace dataspace, + const std::vector& damage) = 0; + virtual Error setColorMode(Display display, ColorMode mode) = 0; + virtual Error setColorTransform(Display display, const float* matrix, ColorTransform hint) = 0; + virtual Error setOutputBuffer(Display display, const native_handle_t* buffer, + int releaseFence) = 0; + virtual Error setPowerMode(Display display, IComposerClient::PowerMode mode) = 0; + virtual Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) = 0; + + virtual Error setClientTargetSlotCount(Display display) = 0; + + virtual Error validateDisplay(Display display, uint32_t* outNumTypes, + uint32_t* outNumRequests) = 0; + + virtual Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes, + uint32_t* outNumRequests, int* outPresentFence, + uint32_t* state) = 0; + + virtual Error setCursorPosition(Display display, Layer layer, int32_t x, int32_t y) = 0; + /* see setClientTarget for the purpose of slot */ + virtual Error setLayerBuffer(Display display, Layer layer, uint32_t slot, + const sp& buffer, int acquireFence) = 0; + virtual Error setLayerSurfaceDamage(Display display, Layer layer, + const std::vector& damage) = 0; + virtual Error setLayerBlendMode(Display display, Layer layer, + IComposerClient::BlendMode mode) = 0; + virtual Error setLayerColor(Display display, Layer layer, + const IComposerClient::Color& color) = 0; + virtual Error setLayerCompositionType(Display display, Layer layer, + IComposerClient::Composition type) = 0; + virtual Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) = 0; + virtual Error setLayerDisplayFrame(Display display, Layer layer, + const IComposerClient::Rect& frame) = 0; + virtual Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) = 0; + virtual Error setLayerSidebandStream(Display display, Layer layer, + const native_handle_t* stream) = 0; + virtual Error setLayerSourceCrop(Display display, Layer layer, + const IComposerClient::FRect& crop) = 0; + virtual Error setLayerTransform(Display display, Layer layer, Transform transform) = 0; + virtual Error setLayerVisibleRegion(Display display, Layer layer, + const std::vector& visible) = 0; + virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0; + virtual Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) = 0; +}; + +namespace impl { + class CommandReader : public CommandReaderBase { public: ~CommandReader(); @@ -134,123 +246,111 @@ private: }; // Composer is a wrapper to IComposer, a proxy to server-side composer. -class Composer { +class Composer final : public Hwc2::Composer { public: Composer(const std::string& serviceName); + ~Composer() override; - std::vector getCapabilities(); - std::string dumpDebugInfo(); + std::vector getCapabilities() override; + std::string dumpDebugInfo() override; - void registerCallback(const sp& callback); + void registerCallback(const sp& callback) override; // 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(); + bool isRemote() override; // Reset all pending commands in the command buffer. Useful if you want to // skip a frame but have already queued some commands. - void resetCommands(); + void resetCommands() override; // Explicitly flush all pending commands in the command buffer. - Error executeCommands(); + Error executeCommands() override; - uint32_t getMaxVirtualDisplayCount(); - bool isUsingVrComposer() const { return mIsUsingVrComposer; } - Error createVirtualDisplay(uint32_t width, uint32_t height, - PixelFormat* format, Display* outDisplay); - Error destroyVirtualDisplay(Display display); + uint32_t getMaxVirtualDisplayCount() override; + bool isUsingVrComposer() const override { return mIsUsingVrComposer; } + Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, + Display* outDisplay) override; + Error destroyVirtualDisplay(Display display) override; - Error acceptDisplayChanges(Display display); + Error acceptDisplayChanges(Display display) override; - Error createLayer(Display display, Layer* outLayer); - Error destroyLayer(Display display, Layer layer); + Error createLayer(Display display, Layer* outLayer) override; + Error destroyLayer(Display display, Layer layer) override; - Error getActiveConfig(Display display, Config* outConfig); - Error getChangedCompositionTypes(Display display, - std::vector* outLayers, - std::vector* outTypes); - Error getColorModes(Display display, std::vector* outModes); - Error getDisplayAttribute(Display display, Config config, - IComposerClient::Attribute attribute, int32_t* outValue); + Error getActiveConfig(Display display, Config* outConfig) override; + Error getChangedCompositionTypes(Display display, std::vector* outLayers, + std::vector* outTypes) override; + Error getColorModes(Display display, std::vector* outModes) override; + Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute, + int32_t* outValue) override; Error getDisplayConfigs(Display display, std::vector* outConfigs); - Error getDisplayName(Display display, std::string* outName); + Error getDisplayName(Display display, std::string* outName) override; Error getDisplayRequests(Display display, uint32_t* outDisplayRequestMask, - std::vector* outLayers, - std::vector* outLayerRequestMasks); + std::vector* outLayers, + std::vector* outLayerRequestMasks) override; - Error getDisplayType(Display display, - IComposerClient::DisplayType* outType); - Error getDozeSupport(Display display, bool* outSupport); - Error getHdrCapabilities(Display display, std::vector* outTypes, - float* outMaxLuminance, float* outMaxAverageLuminance, - float* outMinLuminance); + Error getDisplayType(Display display, IComposerClient::DisplayType* outType) override; + Error getDozeSupport(Display display, bool* outSupport) override; + Error getHdrCapabilities(Display display, std::vector* outTypes, float* outMaxLuminance, + float* outMaxAverageLuminance, float* outMinLuminance) override; Error getReleaseFences(Display display, std::vector* outLayers, - std::vector* outReleaseFences); + std::vector* outReleaseFences) override; - Error presentDisplay(Display display, int* outPresentFence); + Error presentDisplay(Display display, int* outPresentFence) override; - Error setActiveConfig(Display display, Config config); + Error setActiveConfig(Display display, Config config) override; /* * The composer caches client targets internally. When target is nullptr, * the composer uses slot to look up the client target from its cache. * When target is not nullptr, the cache is updated with the new target. */ - Error setClientTarget(Display display, uint32_t slot, - const sp& target, - int acquireFence, Dataspace dataspace, - const std::vector& damage); - Error setColorMode(Display display, ColorMode mode); - Error setColorTransform(Display display, const float* matrix, - ColorTransform hint); + Error setClientTarget(Display display, uint32_t slot, const sp& target, + int acquireFence, Dataspace dataspace, + const std::vector& damage) override; + Error setColorMode(Display display, ColorMode mode) override; + Error setColorTransform(Display display, const float* matrix, ColorTransform hint) override; Error setOutputBuffer(Display display, const native_handle_t* buffer, - int releaseFence); - Error setPowerMode(Display display, IComposerClient::PowerMode mode); - Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled); + int releaseFence) override; + Error setPowerMode(Display display, IComposerClient::PowerMode mode) override; + Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override; - Error setClientTargetSlotCount(Display display); + Error setClientTargetSlotCount(Display display) override; Error validateDisplay(Display display, uint32_t* outNumTypes, - uint32_t* outNumRequests); + uint32_t* outNumRequests) override; - Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes, - uint32_t* outNumRequests, - int* outPresentFence, - uint32_t* state); + Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes, uint32_t* outNumRequests, + int* outPresentFence, uint32_t* state) override; - Error setCursorPosition(Display display, Layer layer, - int32_t x, int32_t y); + Error setCursorPosition(Display display, Layer layer, int32_t x, int32_t y) override; /* see setClientTarget for the purpose of slot */ Error setLayerBuffer(Display display, Layer layer, uint32_t slot, - const sp& buffer, int acquireFence); + const sp& buffer, int acquireFence) override; Error setLayerSurfaceDamage(Display display, Layer layer, - const std::vector& damage); - Error setLayerBlendMode(Display display, Layer layer, - IComposerClient::BlendMode mode); - Error setLayerColor(Display display, Layer layer, - const IComposerClient::Color& color); + const std::vector& damage) override; + Error setLayerBlendMode(Display display, Layer layer, IComposerClient::BlendMode mode) override; + Error setLayerColor(Display display, Layer layer, const IComposerClient::Color& color) override; Error setLayerCompositionType(Display display, Layer layer, - IComposerClient::Composition type); - Error setLayerDataspace(Display display, Layer layer, - Dataspace dataspace); + IComposerClient::Composition type) override; + Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) override; Error setLayerDisplayFrame(Display display, Layer layer, - const IComposerClient::Rect& frame); - Error setLayerPlaneAlpha(Display display, Layer layer, - float alpha); + const IComposerClient::Rect& frame) override; + Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) override; Error setLayerSidebandStream(Display display, Layer layer, - const native_handle_t* stream); + const native_handle_t* stream) override; Error setLayerSourceCrop(Display display, Layer layer, - const IComposerClient::FRect& crop); - Error setLayerTransform(Display display, Layer layer, - Transform transform); + const IComposerClient::FRect& crop) override; + Error setLayerTransform(Display display, Layer layer, Transform transform) override; Error setLayerVisibleRegion(Display display, Layer layer, - const std::vector& visible); - Error setLayerZOrder(Display display, Layer layer, uint32_t z); - Error setLayerInfo(Display display, Layer layer, uint32_t type, - uint32_t appId); + const std::vector& visible) override; + Error setLayerZOrder(Display display, Layer layer, uint32_t z) override; + Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) override; + private: class CommandWriter : public CommandWriterBase { public: @@ -287,6 +387,8 @@ private: const bool mIsUsingVrComposer; }; +} // namespace impl + } // namespace Hwc2 } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 070b691502..bcba35f248 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -84,12 +84,7 @@ private: // Device methods -Device::Device(const std::string& serviceName) - : mComposer(std::make_unique(serviceName)), - mCapabilities(), - mDisplays(), - mRegisteredCallback(false) -{ +Device::Device(std::unique_ptr composer) : mComposer(std::move(composer)) { loadCapabilities(); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 7b98b3e11d..aade4e0b0d 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -78,9 +78,7 @@ class ComposerCallback { class Device { 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); + explicit Device(std::unique_ptr composer); void registerCallback(ComposerCallback* callback, int32_t sequenceId); @@ -119,7 +117,7 @@ private: std::unique_ptr mComposer; std::unordered_set mCapabilities; std::unordered_map> mDisplays; - bool mRegisteredCallback; + bool mRegisteredCallback = false; }; // Convenience C++ class to access hwc2_device_t Display functions directly. diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 7eb399843c..2cafd8e9f9 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -59,25 +59,10 @@ namespace android { // --------------------------------------------------------------------------- -HWComposer::HWComposer(const std::string& serviceName) - : mHwcDevice(), - mDisplayData(2), - mFreeDisplaySlots(), - mHwcDisplaySlots(), - mCBContext(), - mVSyncCounts(), - mRemainingHwcVirtualDisplays(0) -{ - for (size_t i=0 ; i(serviceName); - mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount(); -} +HWComposer::HWComposer(std::unique_ptr composer) + : mHwcDevice(std::make_unique(std::move(composer))) {} -HWComposer::~HWComposer() {} +HWComposer::~HWComposer() = default; void HWComposer::registerCallback(HWC2::ComposerCallback* callback, int32_t sequenceId) { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 2e4f5d403c..abb0fcbd39 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -59,12 +59,14 @@ class NativeHandle; class Region; class String8; +namespace Hwc2 { +class Composer; +} // namespace Hwc2 + class HWComposer { public: - // Uses the named composer service. Valid choices for normal use - // are 'default' and 'vr'. - HWComposer(const std::string& serviceName); + explicit HWComposer(std::unique_ptr composer); ~HWComposer(); @@ -199,19 +201,20 @@ private: }; std::unique_ptr mHwcDevice; - std::vector mDisplayData; + std::vector mDisplayData{HWC_NUM_PHYSICAL_DISPLAY_TYPES}; std::set mFreeDisplaySlots; std::unordered_map mHwcDisplaySlots; // protect mDisplayData from races between prepare and dump mutable Mutex mDisplayLock; - cb_context* mCBContext; - size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES]; - uint32_t mRemainingHwcVirtualDisplays; + cb_context* mCBContext = nullptr; + size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES]{0, 0}; + uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()}; // protected by mLock mutable Mutex mLock; - mutable std::unordered_map mLastHwVSync; + mutable std::unordered_map mLastHwVSync{ + {{HWC_DISPLAY_PRIMARY, 0}, {HWC_DISPLAY_EXTERNAL, 0}}}; // thread-safe mutable Mutex mVsyncLock; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1054c32043..1380b01a1c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -593,7 +593,8 @@ void SurfaceFlinger::init() { LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, "Starting with vr flinger active is not currently supported."); - getBE().mHwc.reset(new HWComposer(getBE().mHwcServiceName)); + getBE().mHwc.reset( + new HWComposer(std::make_unique(getBE().mHwcServiceName))); getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId); // Process any initial hotplug and resulting display changes. processDisplayHotplugEventsLocked(); @@ -1342,7 +1343,8 @@ void SurfaceFlinger::updateVrFlinger() { resetDisplayState(); getBE().mHwc.reset(); // Delete the current instance before creating the new one - getBE().mHwc.reset(new HWComposer(vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName)); + getBE().mHwc.reset(new HWComposer(std::make_unique( + vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName))); getBE().mHwc->registerCallback(this, ++getBE().mComposerSequenceId); LOG_ALWAYS_FATAL_IF(!getBE().mHwc->getComposer()->isRemote(), -- cgit v1.2.3-59-g8ed1b From 144e116f45f196396f0d59d5fc09766ab618f885 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 20 Dec 2017 16:44:52 -0800 Subject: SF: Separate RenderEngine into interface and impl This allows the RenderEngine to be substituted by a GMock for tests. RE::RenderEngine is now a pure virtual interface class. RE::impl::RenderEngine is the normal/base implementation. Similarly, RE::Image and RE::Surface are pure virtual interfaces. RE::impl::Image and RE::impl::Surface are the normal implementations. Test: Builds Bug: None Change-Id: Ib5e658df4bb4efc1a9c0ae95feaf0c1e052cdc94 --- services/surfaceflinger/BufferLayer.cpp | 4 +- services/surfaceflinger/BufferLayerConsumer.cpp | 21 ++- services/surfaceflinger/BufferLayerConsumer.h | 22 ++- services/surfaceflinger/ColorLayer.cpp | 2 +- services/surfaceflinger/DisplayDevice.cpp | 30 +-- services/surfaceflinger/DisplayDevice.h | 2 +- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/Layer.h | 2 +- .../RenderEngine/GLES20RenderEngine.cpp | 6 +- .../RenderEngine/GLES20RenderEngine.h | 7 +- services/surfaceflinger/RenderEngine/Image.cpp | 5 + services/surfaceflinger/RenderEngine/Image.h | 23 ++- .../surfaceflinger/RenderEngine/RenderEngine.cpp | 76 +++++--- .../surfaceflinger/RenderEngine/RenderEngine.h | 209 ++++++++++++++------- services/surfaceflinger/RenderEngine/Surface.cpp | 5 + services/surfaceflinger/RenderEngine/Surface.h | 50 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 22 ++- services/surfaceflinger/SurfaceFlinger.h | 19 +- 18 files changed, 336 insertions(+), 171 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 4d4c9fcc3d..3dbc136205 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -200,7 +200,7 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure()); - RenderEngine& engine(mFlinger->getRenderEngine()); + auto& engine(mFlinger->getRenderEngine()); if (!blackOutLayer) { // TODO: we could be more subtle with isFixedSize() @@ -817,7 +817,7 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT texCoords[2] = vec2(right, 1.0f - bottom); texCoords[3] = vec2(right, 1.0f - top); - RenderEngine& engine(mFlinger->getRenderEngine()); + auto& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */, getColor()); engine.setSourceDataSpace(mCurrentState.dataSpace); diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 4d9b43f52e..46ec0e322b 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -23,6 +23,7 @@ #include "DispSync.h" #include "Layer.h" +#include "RenderEngine/Image.h" #include "RenderEngine/RenderEngine.h" #include @@ -56,8 +57,8 @@ namespace android { static const mat4 mtxIdentity; -BufferLayerConsumer::BufferLayerConsumer(const sp& bq, RenderEngine& engine, - uint32_t tex, Layer* layer) +BufferLayerConsumer::BufferLayerConsumer(const sp& bq, + RE::RenderEngine& engine, uint32_t tex, Layer* layer) : ConsumerBase(bq, false), mCurrentCrop(Rect::EMPTY_RECT), mCurrentTransform(0), @@ -359,7 +360,7 @@ status_t BufferLayerConsumer::bindTextureImageLocked() { if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == nullptr) { BLC_LOGE("bindTextureImage: no currently-bound texture"); - mRE.bindExternalTextureImage(mTexName, RE::Image(mRE)); + mRE.bindExternalTextureImage(mTexName, *mRE.createImage()); return NO_INIT; } @@ -367,7 +368,7 @@ status_t BufferLayerConsumer::bindTextureImageLocked() { status_t err = mCurrentTextureImage->createIfNeeded(imageCrop); if (err != NO_ERROR) { BLC_LOGW("bindTextureImage: can't create image on slot=%d", mCurrentTexture); - mRE.bindExternalTextureImage(mTexName, RE::Image(mRE)); + mRE.bindExternalTextureImage(mTexName, *mRE.createImage()); return UNKNOWN_ERROR; } @@ -604,13 +605,15 @@ void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const ConsumerBase::dumpLocked(result, prefix); } -BufferLayerConsumer::Image::Image(sp graphicBuffer, const RenderEngine& engine) +BufferLayerConsumer::Image::Image(sp graphicBuffer, RE::RenderEngine& engine) : mGraphicBuffer(graphicBuffer), - mImage{engine}, + mImage{engine.createImage()}, mCreated(false), mCropWidth(0), mCropHeight(0) {} +BufferLayerConsumer::Image::~Image() = default; + status_t BufferLayerConsumer::Image::createIfNeeded(const Rect& imageCrop) { const int32_t cropWidth = imageCrop.width(); const int32_t cropHeight = imageCrop.height(); @@ -618,9 +621,9 @@ status_t BufferLayerConsumer::Image::createIfNeeded(const Rect& imageCrop) { return OK; } - mCreated = mImage.setNativeWindowBuffer(mGraphicBuffer->getNativeBuffer(), - mGraphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED, - cropWidth, cropHeight); + mCreated = mImage->setNativeWindowBuffer(mGraphicBuffer->getNativeBuffer(), + mGraphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED, + cropWidth, cropHeight); if (mCreated) { mCropWidth = cropWidth; mCropHeight = cropHeight; diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index a0272b3622..11048d8df8 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -17,8 +17,6 @@ #ifndef ANDROID_BUFFERLAYERCONSUMER_H #define ANDROID_BUFFERLAYERCONSUMER_H -#include "RenderEngine/Image.h" - #include #include #include @@ -36,9 +34,13 @@ namespace android { class DispSync; class Layer; -class RenderEngine; class String8; +namespace RE { +class RenderEngine; +class Image; +} // namespace RE + /* * BufferLayerConsumer consumes buffers of graphics data from a BufferQueue, * and makes them available to RenderEngine as a texture. @@ -70,8 +72,8 @@ public: // BufferLayerConsumer constructs a new BufferLayerConsumer object. The // tex parameter indicates the name of the RenderEngine texture to which // images are to be streamed. - BufferLayerConsumer(const sp& bq, RenderEngine& engine, uint32_t tex, - Layer* layer); + BufferLayerConsumer(const sp& bq, RE::RenderEngine& engine, + uint32_t tex, Layer* layer); // Sets the contents changed listener. This should be used instead of // ConsumerBase::setFrameAvailableListener(). @@ -220,7 +222,7 @@ private: // also only creating new RE::Images from buffers when required. class Image : public LightRefBase { public: - Image(sp graphicBuffer, const RenderEngine& engine); + Image(sp graphicBuffer, RE::RenderEngine& engine); Image(const Image& rhs) = delete; Image& operator=(const Image& rhs) = delete; @@ -234,18 +236,18 @@ private: return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle; } - const RE::Image& image() const { return mImage; } + const RE::Image& image() const { return *mImage; } private: // Only allow instantiation using ref counting. friend class LightRefBase; - virtual ~Image() = default; + virtual ~Image(); // mGraphicBuffer is the buffer that was used to create this image. sp mGraphicBuffer; // mImage is the image created from mGraphicBuffer. - RE::Image mImage; + std::unique_ptr mImage; bool mCreated; int32_t mCropWidth; int32_t mCropHeight; @@ -349,7 +351,7 @@ private: // setFilteringEnabled(). bool mFilteringEnabled; - RenderEngine& mRE; + RE::RenderEngine& mRE; // mTexName is the name of the RenderEngine texture to which streamed // images will be bound when bindTexImage is called. It is set at diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 10e77903ba..80a90a7d31 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -48,7 +48,7 @@ void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, if (s.color.a > 0) { Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); computeGeometry(renderArea, mesh, useIdentityTransform); - RenderEngine& engine(mFlinger->getRenderEngine()); + auto& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */, true /* disableTexture */, s.color); engine.drawMesh(mesh); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index cf70529b53..d40666e6f1 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -84,7 +84,7 @@ DisplayDevice::DisplayDevice( mHwcDisplayId(hwcId), mDisplayToken(displayToken), mDisplaySurface(displaySurface), - mSurface{flinger->getRenderEngine()}, + mSurface{flinger->getRenderEngine().createSurface()}, mDisplayWidth(), mDisplayHeight(), mPageFlipCount(), @@ -106,11 +106,11 @@ DisplayDevice::DisplayDevice( /* * Create our display's surface */ - mSurface.setCritical(mType == DisplayDevice::DISPLAY_PRIMARY); - mSurface.setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL); - mSurface.setNativeWindow(window); - mDisplayWidth = mSurface.queryWidth(); - mDisplayHeight = mSurface.queryHeight(); + mSurface->setCritical(mType == DisplayDevice::DISPLAY_PRIMARY); + mSurface->setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL); + mSurface->setNativeWindow(window); + mDisplayWidth = mSurface->queryWidth(); + mDisplayHeight = mSurface->queryHeight(); // Make sure that composition can never be stalled by a virtual display // consumer that isn't processing buffers fast enough. We have to do this @@ -207,7 +207,7 @@ status_t DisplayDevice::prepareFrame(HWComposer& hwc) { void DisplayDevice::swapBuffers(HWComposer& hwc) const { if (hwc.hasClientComposition(mHwcDisplayId) || hwc.hasFlipClientTargetRequest(mHwcDisplayId)) { - mSurface.swapBuffers(); + mSurface->swapBuffers(); } status_t result = mDisplaySurface->advanceFrame(); @@ -222,7 +222,7 @@ void DisplayDevice::onSwapBuffersCompleted() const { } bool DisplayDevice::makeCurrent() const { - bool success = mFlinger->getRenderEngine().setCurrentSurface(mSurface); + bool success = mFlinger->getRenderEngine().setCurrentSurface(*mSurface); setViewportAndProjection(); return success; } @@ -360,14 +360,14 @@ status_t DisplayDevice::orientationToTransfrom( void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) { dirtyRegion.set(getBounds()); - mSurface.setNativeWindow(nullptr); + mSurface->setNativeWindow(nullptr); mDisplaySurface->resizeBuffers(newWidth, newHeight); ANativeWindow* const window = mNativeWindow.get(); - mSurface.setNativeWindow(window); - mDisplayWidth = mSurface.queryWidth(); - mDisplayHeight = mSurface.queryHeight(); + mSurface->setNativeWindow(window); + mDisplayWidth = mSurface->queryWidth(); + mDisplayHeight = mSurface->queryHeight(); LOG_FATAL_IF(mDisplayWidth != newWidth, "Unable to set new width to %d", newWidth); @@ -474,9 +474,9 @@ void DisplayDevice::dump(String8& result) const { "(%d:%d:%d:%d), orient=%2d (type=%08x), " "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n", mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, window, - mSurface.queryRedSize(), mSurface.queryGreenSize(), mSurface.queryBlueSize(), - mSurface.queryAlphaSize(), mOrientation, tr.getType(), - getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig, + mSurface->queryRedSize(), mSurface->queryGreenSize(), + mSurface->queryBlueSize(), mSurface->queryAlphaSize(), mOrientation, + tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig, mVisibleLayersSortedByZ.size()); result.appendFormat(" v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d]," "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n", diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index a4706701a8..d5ed15fa28 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -187,7 +187,7 @@ private: sp mNativeWindow; sp mDisplaySurface; - RE::Surface mSurface; + std::unique_ptr mSurface; int mDisplayWidth; int mDisplayHeight; mutable uint32_t mPageFlipCount; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 067a09fb5d..78dd40b32f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -719,7 +719,7 @@ void Layer::draw(const RenderArea& renderArea) const { void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue, float alpha) const { - RenderEngine& engine(mFlinger->getRenderEngine()); + auto& engine(mFlinger->getRenderEngine()); computeGeometry(renderArea, getBE().mMesh, false); engine.setupFillWithColor(red, green, blue, alpha); engine.drawMesh(getBE().mMesh); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index c63399e876..3671a2bb32 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -90,7 +90,7 @@ struct CompositionInfo { hwc_color_t color; } hwc; struct { - RenderEngine* renderEngine; + RE::RenderEngine* renderEngine; Mesh* mesh; } renderEngine; }; diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 34d968df6b..9ecf8ce2e7 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -105,6 +105,8 @@ void writePPM(const char* basename, GLuint width, GLuint height) { // --------------------------------------------------------------------------- namespace android { +namespace RE { +namespace impl { // --------------------------------------------------------------------------- GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) @@ -379,7 +381,9 @@ void GLES20RenderEngine::dump(String8& result) { } // --------------------------------------------------------------------------- -}; // namespace android +} // namespace impl +} // namespace RE +} // namespace android // --------------------------------------------------------------------------- #if defined(__gl_h_) diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index f3af5479c6..6e86ea2680 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -35,6 +35,9 @@ class String8; class Mesh; class Texture; +namespace RE { +namespace impl { + class GLES20RenderEngine : public RenderEngine { GLuint mProtectedTexName; GLint mMaxViewportDims[2]; @@ -105,7 +108,9 @@ protected: }; // --------------------------------------------------------------------------- -}; // namespace android +} // namespace impl +} // namespace RE +} // namespace android // --------------------------------------------------------------------------- #endif /* SF_GLES20RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/RenderEngine/Image.cpp b/services/surfaceflinger/RenderEngine/Image.cpp index 1f8e75a0ae..0d06422a41 100644 --- a/services/surfaceflinger/RenderEngine/Image.cpp +++ b/services/surfaceflinger/RenderEngine/Image.cpp @@ -26,6 +26,10 @@ namespace android { namespace RE { +Image::~Image() = default; + +namespace impl { + Image::Image(const RenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {} Image::~Image() { @@ -83,5 +87,6 @@ bool Image::setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, return true; } +} // namespace impl } // namespace RE } // namespace android diff --git a/services/surfaceflinger/RenderEngine/Image.h b/services/surfaceflinger/RenderEngine/Image.h index f55aa59a8a..1ae7e09cba 100644 --- a/services/surfaceflinger/RenderEngine/Image.h +++ b/services/surfaceflinger/RenderEngine/Image.h @@ -24,30 +24,39 @@ struct ANativeWindowBuffer; namespace android { - -class RenderEngine; - namespace RE { class Image { public: - Image(const RenderEngine& engine); - ~Image(); + virtual ~Image() = 0; + virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, + int32_t cropWidth, int32_t cropHeight) = 0; +}; + +namespace impl { + +class RenderEngine; + +class Image : public RE::Image { +public: + explicit Image(const RenderEngine& engine); + ~Image() override; Image(const Image&) = delete; Image& operator=(const Image&) = delete; bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, int32_t cropWidth, - int32_t cropHeight); + int32_t cropHeight) override; private: // methods internal to RenderEngine - friend class android::RenderEngine; + friend class RenderEngine; EGLSurface getEGLImage() const { return mEGLImage; } EGLDisplay mEGLDisplay; EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR; }; +} // namespace impl } // namespace RE } // namespace android diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 22016edd85..4c878aee31 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -37,8 +37,13 @@ extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy // --------------------------------------------------------------------------- namespace android { +namespace RE { // --------------------------------------------------------------------------- +RenderEngine::~RenderEngine() = default; + +namespace impl { + std::unique_ptr RenderEngine::create(int hwcFormat, uint32_t featureFlags) { // initialize EGL for the default display EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); @@ -137,9 +142,7 @@ std::unique_ptr RenderEngine::create(int hwcFormat, uint32_t featu bool RenderEngine::overrideUseContextPriorityFromConfig(bool useContextPriority) { OptionalBool ret; - ISurfaceFlingerConfigs::getService()->useContextPriority([&ret](OptionalBool b) { - ret = b; - }); + ISurfaceFlingerConfigs::getService()->useContextPriority([&ret](OptionalBool b) { ret = b; }); if (ret.specified) { return ret.value; } else { @@ -177,7 +180,22 @@ bool RenderEngine::isCurrent() const { return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext(); } -bool RenderEngine::setCurrentSurface(const RE::Surface& surface) { +std::unique_ptr RenderEngine::createSurface() { + return std::make_unique(*this); +} + +std::unique_ptr RenderEngine::createImage() { + return std::make_unique(*this); +} + +bool RenderEngine::setCurrentSurface(const android::RE::Surface& surface) { + // Note: RE::Surface is an abstract interface. This implementation only ever + // creates RE::impl::Surface's, so it is safe to just cast to the actual + // type. + return setCurrentSurface(static_cast(surface)); +} + +bool RenderEngine::setCurrentSurface(const android::RE::impl::Surface& surface) { bool success = true; EGLSurface eglSurface = surface.getEGLSurface(); if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) { @@ -349,7 +367,14 @@ void RenderEngine::deleteTextures(size_t count, uint32_t const* names) { glDeleteTextures(count, names); } -void RenderEngine::bindExternalTextureImage(uint32_t texName, const RE::Image& image) { +void RenderEngine::bindExternalTextureImage(uint32_t texName, const android::RE::Image& image) { + // Note: RE::Image is an abstract interface. This implementation only ever + // creates RE::impl::Image's, so it is safe to just cast to the actual type. + return bindExternalTextureImage(texName, static_cast(image)); +} + +void RenderEngine::bindExternalTextureImage(uint32_t texName, + const android::RE::impl::Image& image) { const GLenum target = GL_TEXTURE_EXTERNAL_OES; glBindTexture(target, texName); @@ -375,34 +400,33 @@ void RenderEngine::dump(String8& result) { // --------------------------------------------------------------------------- -RenderEngine::BindNativeBufferAsFramebuffer::BindNativeBufferAsFramebuffer( - RenderEngine& engine, ANativeWindowBuffer* buffer) - : mEngine(engine) { - mImage = eglCreateImageKHR(mEngine.mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, - buffer, nullptr); - if (mImage == EGL_NO_IMAGE_KHR) { - mStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; +void RenderEngine::bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, + RE::BindNativeBufferAsFramebuffer* bindHelper) { + bindHelper->mImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, + buffer, nullptr); + if (bindHelper->mImage == EGL_NO_IMAGE_KHR) { + bindHelper->mStatus = NO_MEMORY; return; } - mEngine.bindImageAsFramebuffer(mImage, &mTexName, &mFbName, &mStatus); + uint32_t glStatus; + bindImageAsFramebuffer(bindHelper->mImage, &bindHelper->mTexName, &bindHelper->mFbName, + &glStatus); - ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d", - mStatus); + ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d", + glStatus); + + bindHelper->mStatus = glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE; } -RenderEngine::BindNativeBufferAsFramebuffer::~BindNativeBufferAsFramebuffer() { - if (mImage == EGL_NO_IMAGE_KHR) { +void RenderEngine::unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) { + if (bindHelper->mImage == EGL_NO_IMAGE_KHR) { return; } // back to main framebuffer - mEngine.unbindFramebuffer(mTexName, mFbName); - eglDestroyImageKHR(mEngine.mEGLDisplay, mImage); -} - -status_t RenderEngine::BindNativeBufferAsFramebuffer::getStatus() const { - return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE; + unbindFramebuffer(bindHelper->mTexName, bindHelper->mFbName); + eglDestroyImageKHR(mEGLDisplay, bindHelper->mImage); } // --------------------------------------------------------------------------- @@ -564,5 +588,7 @@ void RenderEngine::primeCache() const { } // --------------------------------------------------------------------------- -}; // namespace android -// --------------------------------------------------------------------------- + +} // namespace impl +} // namespace RE +} // namespace android diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 67c0d1c139..eacef384b7 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -44,91 +44,63 @@ class Mesh; class Texture; namespace RE { + class Image; class Surface; -} // namespace RE +class BindNativeBufferAsFramebuffer; -class RenderEngine { - enum GlesVersion { - GLES_VERSION_1_0 = 0x10000, - GLES_VERSION_1_1 = 0x10001, - GLES_VERSION_2_0 = 0x20000, - GLES_VERSION_3_0 = 0x30000, - }; - static GlesVersion parseGlesVersion(const char* str); - - EGLDisplay mEGLDisplay; - EGLConfig mEGLConfig; - EGLContext mEGLContext; - void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt); - - virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, - uint32_t* status) = 0; - virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0; - - static bool overrideUseContextPriorityFromConfig(bool useContextPriority); - -protected: - RenderEngine(); +namespace impl { +class RenderEngine; +} +class RenderEngine { public: - virtual ~RenderEngine() = 0; - enum FeatureFlag { WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display }; - static std::unique_ptr create(int hwcFormat, uint32_t featureFlags); - static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); + virtual ~RenderEngine() = 0; - void primeCache() const; + virtual std::unique_ptr createSurface() = 0; + virtual std::unique_ptr createImage() = 0; - // dump the extension strings. always call the base class. - virtual void dump(String8& result); + virtual void primeCache() const = 0; - bool supportsImageCrop() const; + // dump the extension strings. always call the base class. + virtual void dump(String8& result) = 0; - bool isCurrent() const; - bool setCurrentSurface(const RE::Surface& surface); - void resetCurrentSurface(); + virtual bool supportsImageCrop() const = 0; - // synchronization + virtual bool isCurrent() const = 0; + virtual bool setCurrentSurface(const RE::Surface& surface) = 0; + virtual void resetCurrentSurface() = 0; + // helpers // flush submits RenderEngine command stream for execution and returns a // native fence fd that is signaled when the execution has completed. It // returns -1 on errors. - base::unique_fd flush(); + virtual base::unique_fd flush() = 0; // finish waits until RenderEngine command stream has been executed. It // returns false on errors. - bool finish(); + virtual bool finish() = 0; // waitFence inserts a wait on an external fence fd to RenderEngine // command stream. It returns false on errors. - bool waitFence(base::unique_fd fenceFd); + virtual bool waitFence(base::unique_fd fenceFd) = 0; - // helpers - void clearWithColor(float red, float green, float blue, float alpha); - void fillRegionWithColor(const Region& region, uint32_t height, float red, float green, - float blue, float alpha); + virtual void clearWithColor(float red, float green, float blue, float alpha) = 0; + virtual void fillRegionWithColor(const Region& region, uint32_t height, float red, float green, + float blue, float alpha) = 0; // common to all GL versions - void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top); - void disableScissor(); - void genTextures(size_t count, uint32_t* names); - void deleteTextures(size_t count, uint32_t const* names); - void bindExternalTextureImage(uint32_t texName, const RE::Image& image); - void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels); - - class BindNativeBufferAsFramebuffer { - RenderEngine& mEngine; - EGLImageKHR mImage; - uint32_t mTexName, mFbName; - uint32_t mStatus; - - public: - BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer); - ~BindNativeBufferAsFramebuffer(); - int getStatus() const; - }; + virtual void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) = 0; + virtual void disableScissor() = 0; + virtual void genTextures(size_t count, uint32_t* names) = 0; + virtual void deleteTextures(size_t count, uint32_t const* names) = 0; + virtual void bindExternalTextureImage(uint32_t texName, const RE::Image& image) = 0; + virtual void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) = 0; + virtual void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, + RE::BindNativeBufferAsFramebuffer* bindHelper) = 0; + virtual void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) = 0; // set-up virtual void checkErrors() const; @@ -145,7 +117,7 @@ public: virtual void setupLayerBlackedOut() = 0; virtual void setupFillWithColor(float r, float g, float b, float a) = 0; - virtual mat4 setupColorTransform(const mat4& /* colorTransform */) { return mat4(); } + virtual mat4 setupColorTransform(const mat4& /* colorTransform */) = 0; virtual void disableTexturing() = 0; virtual void disableBlending() = 0; @@ -156,14 +128,123 @@ public: // queries virtual size_t getMaxTextureSize() const = 0; virtual size_t getMaxViewportDims() const = 0; +}; + +class BindNativeBufferAsFramebuffer { +public: + BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer) + : mEngine(engine) { + mEngine.bindNativeBufferAsFrameBuffer(buffer, this); + } + ~BindNativeBufferAsFramebuffer() { mEngine.unbindNativeBufferAsFrameBuffer(this); } + status_t getStatus() const { return mStatus; } + +protected: + friend impl::RenderEngine; + + RenderEngine& mEngine; + EGLImageKHR mImage; + uint32_t mTexName, mFbName; + status_t mStatus; +}; + +namespace impl { + +class Image; +class Surface; + +class RenderEngine : public RE::RenderEngine { + enum GlesVersion { + GLES_VERSION_1_0 = 0x10000, + GLES_VERSION_1_1 = 0x10001, + GLES_VERSION_2_0 = 0x20000, + GLES_VERSION_3_0 = 0x30000, + }; + static GlesVersion parseGlesVersion(const char* str); + + EGLDisplay mEGLDisplay; + EGLConfig mEGLConfig; + EGLContext mEGLContext; + void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt); + + static bool overrideUseContextPriorityFromConfig(bool useContextPriority); + +protected: + RenderEngine(); + +public: + virtual ~RenderEngine() = 0; + + static std::unique_ptr create(int hwcFormat, uint32_t featureFlags); + + static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); + + // RenderEngine interface implementation + + std::unique_ptr createSurface() override; + std::unique_ptr createImage() override; + + void primeCache() const override; + + // dump the extension strings. always call the base class. + void dump(String8& result) override; + + bool supportsImageCrop() const override; + + bool isCurrent() const; + bool setCurrentSurface(const RE::Surface& surface) override; + void resetCurrentSurface() override; + + // synchronization + + // flush submits RenderEngine command stream for execution and returns a + // native fence fd that is signaled when the execution has completed. It + // returns -1 on errors. + base::unique_fd flush() override; + // finish waits until RenderEngine command stream has been executed. It + // returns false on errors. + bool finish() override; + // waitFence inserts a wait on an external fence fd to RenderEngine + // command stream. It returns false on errors. + bool waitFence(base::unique_fd fenceFd) override; + + // helpers + void clearWithColor(float red, float green, float blue, float alpha) override; + void fillRegionWithColor(const Region& region, uint32_t height, float red, float green, + float blue, float alpha) override; + + // common to all GL versions + void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) override; + void disableScissor() override; + void genTextures(size_t count, uint32_t* names) override; + void deleteTextures(size_t count, uint32_t const* names) override; + void bindExternalTextureImage(uint32_t texName, const RE::Image& image) override; + void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) override; + + void checkErrors() const override; + + mat4 setupColorTransform(const mat4& /* colorTransform */) override { return mat4(); } // internal to RenderEngine EGLDisplay getEGLDisplay() const; EGLConfig getEGLConfig() const; + + // Common implementation + bool setCurrentSurface(const RE::impl::Surface& surface); + void bindExternalTextureImage(uint32_t texName, const RE::impl::Image& image); + + void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer, + RE::BindNativeBufferAsFramebuffer* bindHelper) override; + void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) override; + + // Overriden by each specialization + virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, + uint32_t* status) = 0; + virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0; }; -// --------------------------------------------------------------------------- -}; // namespace android -// --------------------------------------------------------------------------- +} // namespace impl +} // namespace RE +} // namespace android #endif /* SF_RENDERENGINE_H_ */ diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp index a23d9fbb4e..3c29e4b2ea 100644 --- a/services/surfaceflinger/RenderEngine/Surface.cpp +++ b/services/surfaceflinger/RenderEngine/Surface.cpp @@ -23,6 +23,10 @@ namespace android { namespace RE { +Surface::~Surface() = default; + +namespace impl { + Surface::Surface(const RenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) { // RE does not assume any config when EGL_KHR_no_config_context is supported @@ -102,5 +106,6 @@ int32_t Surface::queryHeight() const { return querySurface(EGL_HEIGHT); } +} // namespace impl } // namespace RE } // namespace android diff --git a/services/surfaceflinger/RenderEngine/Surface.h b/services/surfaceflinger/RenderEngine/Surface.h index 8b10be9303..d4d3d8c0f5 100644 --- a/services/surfaceflinger/RenderEngine/Surface.h +++ b/services/surfaceflinger/RenderEngine/Surface.h @@ -23,12 +23,32 @@ struct ANativeWindow; namespace android { - -class RenderEngine; - namespace RE { class Surface { +public: + virtual ~Surface() = 0; + + virtual void setCritical(bool enable) = 0; + virtual void setAsync(bool enable) = 0; + + virtual void setNativeWindow(ANativeWindow* window) = 0; + virtual void swapBuffers() const = 0; + + virtual int32_t queryRedSize() const = 0; + virtual int32_t queryGreenSize() const = 0; + virtual int32_t queryBlueSize() const = 0; + virtual int32_t queryAlphaSize() const = 0; + + virtual int32_t queryWidth() const = 0; + virtual int32_t queryHeight() const = 0; +}; + +namespace impl { + +class RenderEngine; + +class Surface final : public RE::Surface { public: Surface(const RenderEngine& engine); ~Surface(); @@ -36,26 +56,27 @@ public: Surface(const Surface&) = delete; Surface& operator=(const Surface&) = delete; - void setCritical(bool enable) { mCritical = enable; } - void setAsync(bool enable) { mAsync = enable; } + // RE::Surface implementation + void setCritical(bool enable) override { mCritical = enable; } + void setAsync(bool enable) override { mAsync = enable; } - void setNativeWindow(ANativeWindow* window); - void swapBuffers() const; + void setNativeWindow(ANativeWindow* window) override; + void swapBuffers() const override; - int32_t queryRedSize() const; - int32_t queryGreenSize() const; - int32_t queryBlueSize() const; - int32_t queryAlphaSize() const; + int32_t queryRedSize() const override; + int32_t queryGreenSize() const override; + int32_t queryBlueSize() const override; + int32_t queryAlphaSize() const override; - int32_t queryWidth() const; - int32_t queryHeight() const; + int32_t queryWidth() const override; + int32_t queryHeight() const override; private: EGLint queryConfig(EGLint attrib) const; EGLint querySurface(EGLint attrib) const; // methods internal to RenderEngine - friend class android::RenderEngine; + friend class RenderEngine; bool getAsync() const { return mAsync; } EGLSurface getEGLSurface() const { return mEGLSurface; } @@ -69,5 +90,6 @@ private: EGLSurface mEGLSurface = EGL_NO_SURFACE; }; +} // namespace impl } // namespace RE } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1380b01a1c..7ad13e3ef2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -410,12 +410,11 @@ void SurfaceFlinger::bootFinished() void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { class MessageDestroyGLTexture : public MessageBase { - RenderEngine& engine; + RE::RenderEngine& engine; uint32_t texture; public: - MessageDestroyGLTexture(RenderEngine& engine, uint32_t texture) - : engine(engine), texture(texture) { - } + MessageDestroyGLTexture(RE::RenderEngine& engine, uint32_t texture) + : engine(engine), texture(texture) {} virtual bool handler() { engine.deleteTextures(1, &texture); return true; @@ -587,8 +586,11 @@ void SurfaceFlinger::init() { mEventQueue.setEventThread(mSFEventThread.get()); // Get a RenderEngine for the given display / config (can't fail) - getBE().mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, - hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0); + getBE().mRenderEngine = + RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, + hasWideColorDisplay + ? RE::RenderEngine::WIDE_COLOR_SUPPORT + : 0); LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine"); LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, @@ -1473,7 +1475,7 @@ void SurfaceFlinger::doDebugFlashRegions() // and draw the dirty region const int32_t height = hw->getHeight(); - RenderEngine& engine(getRenderEngine()); + auto& engine(getRenderEngine()); engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1); hw->swapBuffers(getHwComposer()); @@ -2856,7 +2858,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev void SurfaceFlinger::drawWormhole(const sp& displayDevice, const Region& region) const { const int32_t height = displayDevice->getHeight(); - RenderEngine& engine(getRenderEngine()); + auto& engine(getRenderEngine()); engine.fillRegionWithColor(region, height, 0, 0, 0, 0); } @@ -4518,7 +4520,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, bool useIdentityTransform) { ATRACE_CALL(); - RenderEngine& engine(getRenderEngine()); + auto& engine(getRenderEngine()); // get screen geometry const auto raWidth = renderArea.getWidth(); @@ -4597,7 +4599,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, // this binds the given EGLImage as a framebuffer for the // duration of this scope. - RenderEngine::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer); + RE::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer); if (bufferBond.getStatus() != NO_ERROR) { ALOGE("got ANWB binding error while taking screenshot"); return INVALID_OPERATION; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 19dd059e97..a17eb70882 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -83,16 +83,19 @@ namespace android { // --------------------------------------------------------------------------- class Client; +class ColorLayer; class DisplayEventConnection; +class EventControlThread; class EventThread; +class InjectVSyncSource; class Layer; -class ColorLayer; class Surface; -class RenderEngine; -class EventControlThread; -class VSyncSource; -class InjectVSyncSource; class SurfaceFlingerBE; +class VSyncSource; + +namespace RE { +class RenderEngine; +} typedef std::function TraverseLayersFunction; @@ -139,7 +142,7 @@ public: const std::string mHwcServiceName; // "default" for real use, something else for testing. // constant members (no synchronization needed for access) - std::unique_ptr mRenderEngine; + std::unique_ptr mRenderEngine; EGLContext mEGLContext; EGLDisplay mEGLDisplay; @@ -301,9 +304,7 @@ public: // TODO: this should be made accessible only to HWComposer const Vector< sp >& getLayerSortedByZForHwcDisplay(int id); - RenderEngine& getRenderEngine() const { - return *getBE().mRenderEngine; - } + RE::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; } bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; -- cgit v1.2.3-59-g8ed1b From 0fcde1b23edcb8105b944df70bf1113cac8f0c15 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 20 Dec 2017 16:50:21 -0800 Subject: SF: Separate EventThread into interface and impl This allows the normal EventThread to be substituted by a GMock for unit tests. The EventThread is now the abstract interface. impl::EventThread is the normal implementation. Test: Builds Bug: None Change-Id: I2c6234a10849f7d34a215d53e5f601895738a5ae --- services/surfaceflinger/EventThread.cpp | 7 +++++- services/surfaceflinger/EventThread.h | 39 ++++++++++++++++++++++++------ services/surfaceflinger/SurfaceFlinger.cpp | 24 +++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 6 ++++- 4 files changed, 55 insertions(+), 21 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index 53d95e21ec..90aab506c8 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -43,6 +43,10 @@ namespace android { // --------------------------------------------------------------------------- +EventThread::~EventThread() = default; + +namespace impl { + EventThread::EventThread(VSyncSource* src, SurfaceFlinger& flinger, bool interceptVSyncs, const char* threadName) : mVSyncSource(src), mFlinger(flinger), mInterceptVSyncs(interceptVSyncs) { @@ -84,7 +88,7 @@ void EventThread::setPhaseOffset(nsecs_t phaseOffset) { mVSyncSource->setPhaseOffset(phaseOffset); } -sp EventThread::createEventConnection() const { +sp EventThread::createEventConnection() const { return new Connection(const_cast(this)); } @@ -404,4 +408,5 @@ status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& e // --------------------------------------------------------------------------- +} // namespace impl } // namespace android diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h index 9ae8fb25b0..708806a22d 100644 --- a/services/surfaceflinger/EventThread.h +++ b/services/surfaceflinger/EventThread.h @@ -56,7 +56,29 @@ public: virtual void setPhaseOffset(nsecs_t phaseOffset) = 0; }; -class EventThread : private VSyncSource::Callback { +class EventThread { +public: + virtual ~EventThread(); + + virtual sp createEventConnection() const = 0; + + // called before the screen is turned off from main thread + virtual void onScreenReleased() = 0; + + // called after the screen is turned on from main thread + virtual void onScreenAcquired() = 0; + + // called when receiving a hotplug event + virtual void onHotplugReceived(int type, bool connected) = 0; + + virtual void dump(String8& result) const = 0; + + virtual void setPhaseOffset(nsecs_t phaseOffset) = 0; +}; + +namespace impl { + +class EventThread : public android::EventThread, private VSyncSource::Callback { class Connection : public BnDisplayEventConnection { public: explicit Connection(EventThread* eventThread); @@ -82,24 +104,24 @@ public: const char* threadName); ~EventThread(); - sp createEventConnection() const; + sp createEventConnection() const override; status_t registerDisplayEventConnection(const sp& connection); void setVsyncRate(uint32_t count, const sp& connection); void requestNextVsync(const sp& connection); // called before the screen is turned off from main thread - void onScreenReleased(); + void onScreenReleased() override; // called after the screen is turned on from main thread - void onScreenAcquired(); + void onScreenAcquired() override; // called when receiving a hotplug event - void onHotplugReceived(int type, bool connected); + void onHotplugReceived(int type, bool connected) override; - void dump(String8& result) const; + void dump(String8& result) const override; - void setPhaseOffset(nsecs_t phaseOffset); + void setPhaseOffset(nsecs_t phaseOffset) override; private: void threadMain(); @@ -139,4 +161,5 @@ private: // --------------------------------------------------------------------------- -}; // namespace android +} // namespace impl +} // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7ad13e3ef2..03f6bdc583 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -574,15 +574,16 @@ void SurfaceFlinger::init() { Mutex::Autolock _l(mStateLock); // start the EventThread - - mEventThreadSource = std::make_unique( - &mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app"); - mEventThread = std::make_unique( - mEventThreadSource.get(), *this, false, "sfEventThread"); - mSfEventThreadSource = std::make_unique( - &mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf"); - mSFEventThread = std::make_unique( - mSfEventThreadSource.get(), *this, true, "appEventThread"); + mEventThreadSource = + std::make_unique(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, + true, "app"); + mEventThread = std::make_unique(mEventThreadSource.get(), *this, false, + "appEventThread"); + mSfEventThreadSource = + std::make_unique(&mPrimaryDispSync, + SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf"); + mSFEventThread = std::make_unique(mSfEventThreadSource.get(), *this, true, + "sfEventThread"); mEventQueue.setEventThread(mSFEventThread.get()); // Get a RenderEngine for the given display / config (can't fail) @@ -1068,8 +1069,9 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) { ALOGV("VSync Injections enabled"); if (mVSyncInjector.get() == nullptr) { mVSyncInjector = std::make_unique(); - mInjectorEventThread = std::make_unique( - mVSyncInjector.get(), *this, false, "injEvThread"); + mInjectorEventThread = + std::make_unique(mVSyncInjector.get(), *this, false, + "injEventThread"); } mEventQueue.setEventThread(mInjectorEventThread.get()); } else { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a17eb70882..b7ebb1bcf3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -93,6 +93,10 @@ class Surface; class SurfaceFlingerBE; class VSyncSource; +namespace impl { +class EventThread; +} // namespace impl + namespace RE { class RenderEngine; } @@ -312,7 +316,7 @@ public: private: friend class Client; friend class DisplayEventConnection; - friend class EventThread; + friend class impl::EventThread; friend class Layer; friend class BufferLayer; friend class MonitoredProducer; -- cgit v1.2.3-59-g8ed1b From ca27f2500cff74ae1e08b3ae06f18e9b3414ffb7 Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 6 Feb 2018 16:46:39 -0800 Subject: Allow destroySurface to get called in transaction. Previously, destroy was always initiated immediatley and could not be synchronized with a client transaction. This change allows destroySurface to be called in the same transaction as other client state updates. Test: Unit tests pass Test: Call from Java fixes bugs. Change-Id: I841359530538961a0187216cc455cc388c0ede77 Fixes: 72953020 Fixes: 71499373 --- libs/gui/LayerState.cpp | 3 + libs/gui/SurfaceComposerClient.cpp | 11 ++++ libs/gui/include/gui/LayerState.h | 3 +- libs/gui/include/gui/SurfaceComposerClient.h | 2 + services/surfaceflinger/SurfaceFlinger.cpp | 96 +++++++++++++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 5 +- 6 files changed, 89 insertions(+), 31 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index b5295f2801..01acc2de20 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -231,6 +231,9 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eReparent; parentHandleForChild = other.parentHandleForChild; } + if (other.what & eDestroySurface) { + what |= eDestroySurface; + } } }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index c40cad3e99..0722038c5b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -472,6 +472,17 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeome return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface( + const sp& sc) { + layer_state_t* s = getLayerStateLocked(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eDestroySurface; + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayStateLocked(const sp& token) { diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index f3fb82feb3..788962e490 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -62,7 +62,8 @@ struct layer_state_t { eDetachChildren = 0x00004000, eRelativeLayerChanged = 0x00008000, eReparent = 0x00010000, - eColorChanged = 0x00020000 + eColorChanged = 0x00020000, + eDestroySurface = 0x00040000 }; layer_state_t() diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 55b96ac93d..10caa76281 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -229,6 +229,8 @@ public: // freezing the total geometry of a surface until a resize is completed. Transaction& setGeometryAppliesWithResize(const sp& sc); + Transaction& destroySurface(const sp& sc); + status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 03f6bdc583..135bfbefa9 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2901,7 +2901,11 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, status_t SurfaceFlinger::removeLayer(const sp& layer, bool topLevelOnly) { Mutex::Autolock _l(mStateLock); + return removeLayerLocked(mStateLock, layer, topLevelOnly); +} +status_t SurfaceFlinger::removeLayerLocked(const Mutex&, const sp& layer, + bool topLevelOnly) { if (layer->isPendingRemoval()) { return NO_ERROR; } @@ -2965,8 +2969,30 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { return old; } +bool SurfaceFlinger::containsAnyInvalidClientState(const Vector& states) { + for (const ComposerState& state : states) { + // Here we need to check that the interface we're given is indeed + // one of our own. A malicious client could give us a nullptr + // IInterface, or one of its own or even one of our own but a + // different type. All these situations would cause us to crash. + if (state.client == nullptr) { + return true; + } + + sp binder = IInterface::asBinder(state.client); + if (binder == nullptr) { + return true; + } + + if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) == nullptr) { + return true; + } + } + return false; +} + void SurfaceFlinger::setTransactionState( - const Vector& state, + const Vector& states, const Vector& displays, uint32_t flags) { @@ -2974,6 +3000,10 @@ void SurfaceFlinger::setTransactionState( Mutex::Autolock _l(mStateLock); uint32_t transactionFlags = 0; + if (containsAnyInvalidClientState(states)) { + return; + } + if (flags & eAnimation) { // For window updates that are part of an animation we must wait for // previous animation "frames" to be handled. @@ -2990,31 +3020,20 @@ void SurfaceFlinger::setTransactionState( } } - size_t count = displays.size(); - for (size_t i=0 ; i binder = IInterface::asBinder(s.client); - if (binder != nullptr) { - if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != nullptr) { - sp client( static_cast(s.client.get()) ); - transactionFlags |= setClientStateLocked(client, s.state); - } - } - } + for (const ComposerState& state : states) { + transactionFlags |= setClientStateLocked(state); + } + + // Iterate through all layers again to determine if any need to be destroyed. Marking layers + // as destroyed should only occur after setting all other states. This is to allow for a + // child re-parent to happen before marking its original parent as destroyed (which would + // then mark the child as destroyed). + for (const ComposerState& state : states) { + setDestroyStateLocked(state); } // If a synchronous transaction is explicitly requested without any changes, force a transaction @@ -3028,7 +3047,7 @@ void SurfaceFlinger::setTransactionState( if (transactionFlags) { if (mInterceptor.isEnabled()) { - mInterceptor.saveTransaction(state, mCurrentState.displays, displays, flags); + mInterceptor.saveTransaction(states, mCurrentState.displays, displays, flags); } // this triggers the transaction @@ -3105,10 +3124,10 @@ uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) return flags; } -uint32_t SurfaceFlinger::setClientStateLocked( - const sp& client, - const layer_state_t& s) -{ +uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState) { + const layer_state_t& s = composerState.state; + sp client(static_cast(composerState.client.get())); + sp layer(client->getLayerUser(s.surface)); if (layer == nullptr) { return 0; @@ -3259,6 +3278,25 @@ uint32_t SurfaceFlinger::setClientStateLocked( return flags; } +void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { + const layer_state_t& state = composerState.state; + sp client(static_cast(composerState.client.get())); + + sp layer(client->getLayerUser(state.surface)); + if (layer == nullptr) { + return; + } + + if (layer->isPendingRemoval()) { + ALOGW("Attempting to destroy on removed layer: %s", layer->getName().string()); + return; + } + + if (state.what & layer_state_t::eDestroySurface) { + removeLayerLocked(mStateLock, layer); + } +} + status_t SurfaceFlinger::createLayer( const String8& name, const sp& client, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b7ebb1bcf3..08c4a5e3b1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -473,8 +473,10 @@ private: // Can only be called from the main thread or with mStateLock held uint32_t setTransactionFlags(uint32_t flags); void commitTransaction(); - uint32_t setClientStateLocked(const sp& client, const layer_state_t& s); + bool containsAnyInvalidClientState(const Vector& states); + uint32_t setClientStateLocked(const ComposerState& composerState); uint32_t setDisplayStateLocked(const DisplayState& s); + void setDestroyStateLocked(const ComposerState& composerState); /* ------------------------------------------------------------------------ * Layer management @@ -506,6 +508,7 @@ private: // remove a layer from SurfaceFlinger immediately status_t removeLayer(const sp& layer, bool topLevelOnly = false); + status_t removeLayerLocked(const Mutex&, const sp& layer, bool topLevelOnly = false); // add a layer to SurfaceFlinger status_t addClientLayer(const sp& client, -- cgit v1.2.3-59-g8ed1b From 12eb423785adba54be4c7112e5198a80d563896e Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 17 Jan 2018 11:54:43 -0800 Subject: SF: Abstract out buffer queue creation Modifies SurfaceFlinger so that the type of the buffer queue producer/consumer pair produced for framebuffers can be changed at runtime. Test: Builds Bug: None Change-Id: If108059c43e5c0d03de9645966d9b8eca2b9ed16 --- services/surfaceflinger/SurfaceFlinger.cpp | 8 ++++---- services/surfaceflinger/SurfaceFlinger.h | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 135bfbefa9..e0dbfaded3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -163,7 +163,7 @@ SurfaceFlingerBE::SurfaceFlingerBE() } SurfaceFlinger::SurfaceFlinger() - : BnSurfaceComposer(), + : BnSurfaceComposer(), mTransactionFlags(0), mTransactionPending(false), mAnimTransactionPending(false), @@ -193,8 +193,8 @@ SurfaceFlinger::SurfaceFlinger() mHasPoweredOff(false), mNumLayers(0), mVrFlingerRequestsDisplay(false), - mMainThreadId(std::this_thread::get_id()) -{ + mMainThreadId(std::this_thread::get_id()), + mCreateBufferQueue(&BufferQueue::createBufferQueue) { ALOGI("SurfaceFlinger is starting"); vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs, @@ -2213,7 +2213,7 @@ void SurfaceFlinger::processDisplayChangesLocked() { sp producer; sp bqProducer; sp bqConsumer; - BufferQueue::createBufferQueue(&bqProducer, &bqConsumer); + mCreateBufferQueue(&bqProducer, &bqConsumer, false); int32_t hwcId = -1; if (state.isVirtualDisplay()) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 08c4a5e3b1..37024ae028 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -87,6 +87,8 @@ class ColorLayer; class DisplayEventConnection; class EventControlThread; class EventThread; +class IGraphicBufferConsumer; +class IGraphicBufferProducer; class InjectVSyncSource; class Layer; class Surface; @@ -822,6 +824,12 @@ private: float mSaturation = 1.0f; bool mForceNativeColorMode = false; + using CreateBufferQueueFunction = + std::function* /* outProducer */, + sp* /* outConsumer */, + bool /* consumerIsSurfaceFlinger */)>; + CreateBufferQueueFunction mCreateBufferQueue; + SurfaceFlingerBE mBE; }; }; // namespace android -- cgit v1.2.3-59-g8ed1b From ccfd682b5280fe638d4e0b4c7841c98aab298788 Mon Sep 17 00:00:00 2001 From: Jiwen 'Steve' Cai Date: Wed, 21 Feb 2018 16:15:58 -0800 Subject: Fix VrFlinger handoff In ag/3368932, hotplug processing was moved to main thread and deferred the actual display devices creation to the next cycle of SurfaceFlinger's main thread. This breaks UpdateVrFlinger logic, which runs on the main thread and assumes all new display devices get created synchronously during the handoff. This CL fixes the issue by allowing synchronous calling processDisplayHotplugEventsLocked() from onHotplugReceived() if and only if the callback is called on main thread. Bug: 72103899 Test: VrApp now renders fine Change-Id: I2abd5d5861e0bb74419f12142f7f7c33190a022c --- services/surfaceflinger/SurfaceFlinger.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 135bfbefa9..ea43c584ac 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1289,6 +1289,11 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t displa mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection}); + if (std::this_thread::get_id() == mMainThreadId) { + // Process all pending hot plug events immediately if we are on the main thread. + processDisplayHotplugEventsLocked(); + } + setTransactionFlags(eDisplayTransactionNeeded); } -- cgit v1.2.3-59-g8ed1b From 4b0e4ddf448f14198c578a71fae888025ab5964f Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 20 Feb 2018 13:04:55 -0800 Subject: surfaceflinger: fix WCG flag in DisplayDevice creation When a display does not support any wide color mode, yet it is plugged when mForceNativeColorMode is true, we would incorrectly mark the display as supporting wide color. We should ignore mForceNativeColorMode entirely in DisplayDevice creation because mForceNativeColorMode may change at runtime. Test: builds Change-Id: Icb245a2e78954b90d6c5461de8f4ef571858d959 --- services/surfaceflinger/SurfaceFlinger.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e7c8bb2aca..0961058957 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2266,9 +2266,8 @@ void SurfaceFlinger::processDisplayChangesLocked() { const wp& display(curr.keyAt(i)); if (dispSurface != nullptr) { - bool useWideColorMode = hasWideColorDisplay; - if (!mForceNativeColorMode) { - bool hasWideColorModes = false; + bool hasWideColorSupport = false; + if (hasWideColorDisplay) { std::vector modes = getHwComposer().getColorModes(state.type); for (android_color_mode_t colorMode : modes) { @@ -2276,13 +2275,12 @@ void SurfaceFlinger::processDisplayChangesLocked() { case HAL_COLOR_MODE_DISPLAY_P3: case HAL_COLOR_MODE_ADOBE_RGB: case HAL_COLOR_MODE_DCI_P3: - hasWideColorModes = true; + hasWideColorSupport = true; break; default: break; } } - useWideColorMode = hasWideColorModes && hasWideColorDisplay; } bool hasHdrSupport = false; @@ -2296,11 +2294,11 @@ void SurfaceFlinger::processDisplayChangesLocked() { sp hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, - dispSurface, producer, useWideColorMode, + dispSurface, producer, hasWideColorSupport, hasHdrSupport); android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; - if (useWideColorMode) { + if (hasWideColorSupport) { defaultColorMode = HAL_COLOR_MODE_SRGB; } setActiveColorModeInternal(hw, defaultColorMode); -- cgit v1.2.3-59-g8ed1b From 69bf10f5ea9b8abce49d49235630388dd57d3e62 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 20 Feb 2018 13:04:50 -0800 Subject: surfaceflinger: simplify P3 support in RE RE always knows how to convert sRGB/P3/BT2020 to P3. The conversion is enabled by SurfaceFlinger whenever the color mode is P3 (and when hasWideColorDisplay is true). This change simplifies or removes some wide color state functions from RE, and moves the burden to SurfaceFlinger. It also changes GLES20RenderEngine::drawMesh to inspect mDataSpace and mOutputDataSpace directly. This allows us to enable the conversion in more cases more easily. For example, we can choose to set the RE output dataspace to P3 even when the display color mode is NATIVE. Test: manual with UiBench Change-Id: I5e701dd6b01764efbbab967dc4a26a4d008dfc09 --- .../RenderEngine/GLES20RenderEngine.cpp | 60 ++++++---------------- .../RenderEngine/GLES20RenderEngine.h | 21 +++----- .../surfaceflinger/RenderEngine/RenderEngine.h | 10 ++-- services/surfaceflinger/SurfaceFlinger.cpp | 20 +++++--- .../tests/unittests/MockRenderEngine.h | 8 ++- 5 files changed, 45 insertions(+), 74 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 9ecf8ce2e7..ea7dc2f1fd 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -210,42 +210,16 @@ void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque } } -void GLES20RenderEngine::setColorMode(android_color_mode mode) { - ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode); - - if (mColorMode == mode) return; - - if (!mPlatformHasWideColor || !mDisplayHasWideColor || mode == HAL_COLOR_MODE_SRGB || - mode == HAL_COLOR_MODE_NATIVE) { - // We are returning back to our default color_mode - mUseWideColor = false; - mWideColorFrameCount = 0; - } else { - mUseWideColor = true; - } - - mColorMode = mode; -} - -void GLES20RenderEngine::setSourceDataSpace(android_dataspace source) { - if (source == HAL_DATASPACE_UNKNOWN) { - // Treat UNKNOWN as SRGB - source = HAL_DATASPACE_V0_SRGB; - } - mDataSpace = source; -} - void GLES20RenderEngine::setSourceY410BT2020(bool enable) { mState.setY410BT2020(enable); } -void GLES20RenderEngine::setWideColor(bool hasWideColor) { - ALOGV("setWideColor: %s", hasWideColor ? "true" : "false"); - mDisplayHasWideColor = hasWideColor; +void GLES20RenderEngine::setSourceDataSpace(android_dataspace source) { + mDataSpace = source; } -bool GLES20RenderEngine::usesWideColor() { - return mUseWideColor; +void GLES20RenderEngine::setOutputDataSpace(android_dataspace dataspace) { + mOutputDataSpace = dataspace; } void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) { @@ -326,17 +300,13 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE, mesh.getByteStride(), mesh.getPositions()); - if (usesWideColor()) { + // DISPLAY_P3 is the only supported wide color output + if (mPlatformHasWideColor && mOutputDataSpace == HAL_DATASPACE_DISPLAY_P3) { Description wideColorState = mState; switch (int(mDataSpace)) { case HAL_DATASPACE_DISPLAY_P3: // input matches output break; - case HAL_DATASPACE_V0_SCRGB_LINEAR: - wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3); - wideColorState.setInputTransferFunction(Description::TransferFunction::LINEAR); - wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB); - break; case HAL_DATASPACE_BT2020_PQ: case HAL_DATASPACE_BT2020_ITU_PQ: wideColorState.setColorMatrix(mState.getColorMatrix() * mBt2020ToDisplayP3); @@ -345,8 +315,13 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { wideColorState.enableToneMapping(true); break; default: + // treat all other dataspaces as sRGB wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3); - wideColorState.setInputTransferFunction(Description::TransferFunction::SRGB); + if ((mDataSpace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_LINEAR) { + wideColorState.setInputTransferFunction(Description::TransferFunction::LINEAR); + } else { + wideColorState.setInputTransferFunction(Description::TransferFunction::SRGB); + } wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB); ALOGV("drawMesh: gamut transform applied"); break; @@ -356,8 +331,9 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); if (outputDebugPPMs) { + static uint64_t wideColorFrameCount = 0; std::ostringstream out; - out << "/data/texture_out" << mWideColorFrameCount++; + out << "/data/texture_out" << wideColorFrameCount++; writePPM(out.str().c_str(), mVpWidth, mVpHeight); } } else { @@ -373,11 +349,9 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { void GLES20RenderEngine::dump(String8& result) { RenderEngine::dump(result); - if (usesWideColor()) { - result.append("Wide-color: On\n"); - } else { - result.append("Wide-color: Off\n"); - } + result.appendFormat("RenderEngine last dataspace conversion: (%s) to (%s)\n", + dataspaceDetails(mDataSpace).c_str(), + dataspaceDetails(mOutputDataSpace).c_str()); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index 6e86ea2680..db3f79281e 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -72,27 +72,20 @@ protected: const half4& color) override; // Color management related functions and state - void setColorMode(android_color_mode mode); - void setSourceDataSpace(android_dataspace source); - void setSourceY410BT2020(bool enable); - void setWideColor(bool hasWideColor); - bool usesWideColor(); - - // Current color mode of display using the render engine - android_color_mode mColorMode = HAL_COLOR_MODE_NATIVE; + void setSourceY410BT2020(bool enable) override; + void setSourceDataSpace(android_dataspace source) override; + void setOutputDataSpace(android_dataspace dataspace) override; // Current dataspace of layer being rendered - android_dataspace mDataSpace = HAL_DATASPACE_V0_SRGB; + android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN; - // Indicate if wide-color mode is needed or not - bool mDisplayHasWideColor = false; - bool mUseWideColor = false; - uint64_t mWideColorFrameCount = 0; + // Current output dataspace of the render engine + android_dataspace mOutputDataSpace = HAL_DATASPACE_UNKNOWN; // Currently only supporting sRGB, BT2020 and DisplayP3 color spaces + const bool mPlatformHasWideColor = false; mat4 mSrgbToDisplayP3; mat4 mBt2020ToDisplayP3; - bool mPlatformHasWideColor = false; virtual void setupLayerTexturing(const Texture& texture); virtual void setupLayerBlackedOut(); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index eacef384b7..d1405740e6 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -108,11 +108,6 @@ public: bool yswap, Transform::orientation_flags rotation) = 0; virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, const half4& color) = 0; - virtual void setColorMode(android_color_mode mode) = 0; - virtual void setSourceDataSpace(android_dataspace source) = 0; - virtual void setSourceY410BT2020(bool enable) = 0; - virtual void setWideColor(bool hasWideColor) = 0; - virtual bool usesWideColor() = 0; virtual void setupLayerTexturing(const Texture& texture) = 0; virtual void setupLayerBlackedOut() = 0; virtual void setupFillWithColor(float r, float g, float b, float a) = 0; @@ -122,6 +117,11 @@ public: virtual void disableTexturing() = 0; virtual void disableBlending() = 0; + // wide color support + virtual void setSourceY410BT2020(bool enable) = 0; + virtual void setSourceDataSpace(android_dataspace source) = 0; + virtual void setOutputDataSpace(android_dataspace dataspace) = 0; + // drawing virtual void drawMesh(const Mesh& mesh) = 0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0961058957..87fd2f1e72 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2738,10 +2738,13 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev if (hasClientComposition) { ALOGV("hasClientComposition"); - getBE().mRenderEngine->setWideColor( - displayDevice->getWideColorSupport() && !mForceNativeColorMode); - getBE().mRenderEngine->setColorMode(mForceNativeColorMode ? - HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode()); + android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN; + if (!mForceNativeColorMode && displayDevice->getWideColorSupport() && + displayDevice->getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) { + outputDataspace = HAL_DATASPACE_DISPLAY_P3; + } + getBE().mRenderEngine->setOutputDataSpace(outputDataspace); + if (!displayDevice->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", displayDevice->getDisplayName().string()); @@ -4596,9 +4599,12 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight); } - engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode); - engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE - : renderArea.getActiveColorMode()); + android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN; + if (!mForceNativeColorMode && renderArea.getWideColorSupport() && + renderArea.getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) { + outputDataspace = HAL_DATASPACE_DISPLAY_P3; + } + getBE().mRenderEngine->setOutputDataSpace(outputDataspace); // make sure to clear all GL error flags engine.checkErrors(); diff --git a/services/surfaceflinger/tests/unittests/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/MockRenderEngine.h index aefbfcf211..6d3e17ff73 100644 --- a/services/surfaceflinger/tests/unittests/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/MockRenderEngine.h @@ -57,17 +57,15 @@ public: MOCK_METHOD6(setViewportAndProjection, void(size_t, size_t, Rect, size_t, bool, Transform::orientation_flags)); MOCK_METHOD4(setupLayerBlending, void(bool, bool, bool, const half4&)); - MOCK_METHOD1(setColorMode, void(android_color_mode)); - MOCK_METHOD1(setSourceDataSpace, void(android_dataspace)); - MOCK_METHOD1(setSourceY410BT2020, void(bool)); - MOCK_METHOD1(setWideColor, void(bool)); - MOCK_METHOD0(usesWideColor, bool()); MOCK_METHOD1(setupLayerTexturing, void(const Texture&)); MOCK_METHOD0(setupLayerBlackedOut, void()); MOCK_METHOD4(setupFillWithColor, void(float, float, float, float)); MOCK_METHOD1(setupColorTransform, mat4(const mat4&)); MOCK_METHOD0(disableTexturing, void()); MOCK_METHOD0(disableBlending, void()); + MOCK_METHOD1(setSourceY410BT2020, void(bool)); + MOCK_METHOD1(setSourceDataSpace, void(android_dataspace)); + MOCK_METHOD1(setOutputDataSpace, void(android_dataspace)); MOCK_METHOD2(bindNativeBufferAsFrameBuffer, void(ANativeWindowBuffer*, RE::BindNativeBufferAsFramebuffer*)); MOCK_METHOD1(unbindNativeBufferAsFrameBuffer, void(RE::BindNativeBufferAsFramebuffer*)); -- cgit v1.2.3-59-g8ed1b From 9a48a8c84bf84dff2aaf51a011b5810d89dddc32 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 20 Feb 2018 14:27:30 -0800 Subject: surfaceflinger: simplify getActiveColorMode check When mForceNativeColorMode is true, getActiveColorMode returns HAL_COLOR_MODE_NATIVE. There is no need to check both. Test: manual with UiBench Change-Id: I3bbf66d85ccb262441b9d216096ec869c529b7e8 --- services/surfaceflinger/SurfaceFlinger.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 87fd2f1e72..c8025b37c5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2739,7 +2739,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev ALOGV("hasClientComposition"); android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN; - if (!mForceNativeColorMode && displayDevice->getWideColorSupport() && + if (displayDevice->getWideColorSupport() && displayDevice->getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) { outputDataspace = HAL_DATASPACE_DISPLAY_P3; } @@ -4600,7 +4600,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, } android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN; - if (!mForceNativeColorMode && renderArea.getWideColorSupport() && + if (renderArea.getWideColorSupport() && renderArea.getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) { outputDataspace = HAL_DATASPACE_DISPLAY_P3; } -- cgit v1.2.3-59-g8ed1b From 101d8dc00001bd282f09a25f10058c77f982c11c Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Tue, 27 Feb 2018 15:42:25 -0800 Subject: SF: Fix mGraphicBufferProducerList This change is primarily to fix a memory leak discovered while investigating bug 73792507. It turned out that while we were adding every new IGBP to SF's list (which it uses for authentication), we were never removing anything from that list, causing us to leak wp<> items. The root cause was some subtlety around MonitoredProducer, which wraps a generic IGBP in order to allow SF to perform some work when one is destroyed. When we were adding elements to mGBPL, we were adding the address of the MonitoredProducer, but upon destruction, the MonitoredProducer was trying to remove the address of its wrapped IGBP, which, naturally, wasn't present in the list. In order to address this, the key functional change here is to pass the IBinder address of the MonitoredProducer from its destructor rather than that of the wrapped IGBP. On top of the bug fix, however, this also switches from a custom MessageBase-derived class to LambdaMessage and converts mGBPL from a SortedVector to a std::set. Bug: 73792507 Test: Manual - log lines to verify mGBPL no longer increases over time Change-Id: Idabae211354561a0f13c8d9e594c7acc4822aab0 --- services/surfaceflinger/MonitoredProducer.cpp | 27 +++++++-------------------- services/surfaceflinger/SurfaceFlinger.cpp | 6 ++++-- services/surfaceflinger/SurfaceFlinger.h | 4 +++- 3 files changed, 14 insertions(+), 23 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index 1a5a85e079..389fbd23e3 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -33,26 +33,13 @@ MonitoredProducer::~MonitoredProducer() { // because we don't know where this destructor is called from. It could be // called with the mStateLock held, leading to a dead-lock (it actually // happens). - class MessageCleanUpList : public MessageBase { - public: - MessageCleanUpList(const sp& flinger, - const wp& producer) - : mFlinger(flinger), mProducer(producer) {} - - virtual ~MessageCleanUpList() {} - - virtual bool handler() { - Mutex::Autolock _l(mFlinger->mStateLock); - mFlinger->mGraphicBufferProducerList.remove(mProducer); - return true; - } - - private: - sp mFlinger; - wp mProducer; - }; - - mFlinger->postMessageAsync(new MessageCleanUpList(mFlinger, asBinder(mProducer))); + sp cleanUpListMessage = + new LambdaMessage([flinger = mFlinger, asBinder = wp(onAsBinder())]() { + Mutex::Autolock lock(flinger->mStateLock); + flinger->mGraphicBufferProducerList.erase(asBinder); + }); + + mFlinger->postMessageAsync(cleanUpListMessage); } status_t MonitoredProducer::requestBuffer(int slot, sp* buf) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ea43c584ac..4d7e4c8249 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -701,7 +701,7 @@ bool SurfaceFlinger::authenticateSurfaceTexture( bool SurfaceFlinger::authenticateSurfaceTextureLocked( const sp& bufferProducer) const { sp surfaceTextureBinder(IInterface::asBinder(bufferProducer)); - return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0; + return mGraphicBufferProducerList.count(surfaceTextureBinder.get()) > 0; } status_t SurfaceFlinger::getSupportedFrameTimestamps( @@ -2893,7 +2893,9 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, parent->addChild(lbc); } - mGraphicBufferProducerList.add(IInterface::asBinder(gbc)); + mGraphicBufferProducerList.insert(IInterface::asBinder(gbc).get()); + LOG_ALWAYS_FATAL_IF(mGraphicBufferProducerList.size() > MAX_LAYERS, + "Suspected IGBP leak"); mLayersAdded = true; mNumLayers++; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 6da1409ab4..b774d49fe6 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -715,7 +715,9 @@ private: bool mTransactionPending; bool mAnimTransactionPending; SortedVector< sp > mLayersPendingRemoval; - SortedVector< wp > mGraphicBufferProducerList; + + // Can't be unordered_set because wp<> isn't hashable + std::set> mGraphicBufferProducerList; // protected by mStateLock (but we could use another lock) bool mLayersRemoved; -- cgit v1.2.3-59-g8ed1b From 578038fc49f83c4c8c4accdce49df404ecd6ad02 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Fri, 9 Mar 2018 12:25:24 -0800 Subject: SurfaceFlinger: Add childLayersOnly variant of capture layers. Currently captureLayers is being used to capture children of abstract buffer-less layers, for example we capture the node representing a Task. Because of animations, etc, the node may have been scaled when we want to take the screenshot, so we solved this problem with an inverse transform in LayerRenderArea. However we have parallel problems for crop, visibility, etc...It seems what we really want from captureLayers is the ability to capture all child layers while ignoring the parent imposed state as if in a parallel hierarchy. I initially considered implementing a parallel hierarchy with layer clones but it seemed much less risky for P to instead reparent the existing hierarchy to a parallel abstract parent on the server side. Bug: 72760590 Test: Existing tests pass. Quickstep works with new implementation. New transaction tests. Change-Id: Ifd2b2f9ed45351d8ed0d7f09be1cd9806ec4abe8 --- libs/gui/ISurfaceComposer.cpp | 7 +- libs/gui/SurfaceComposerClient.cpp | 12 +++- libs/gui/include/gui/ISurfaceComposer.h | 5 +- libs/gui/include/gui/SurfaceComposerClient.h | 4 +- libs/gui/tests/Surface_test.cpp | 4 +- services/surfaceflinger/ContainerLayer.cpp | 14 ++-- services/surfaceflinger/ContainerLayer.h | 10 +-- services/surfaceflinger/Layer.cpp | 6 ++ services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/RenderArea.h | 4 ++ services/surfaceflinger/SurfaceFlinger.cpp | 81 +++++++++++++++++----- services/surfaceflinger/SurfaceFlinger.h | 2 +- services/surfaceflinger/tests/Transaction_test.cpp | 78 +++++++++++++++++++++ 13 files changed, 191 insertions(+), 38 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 5de84ecbab..beda778396 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -132,12 +132,13 @@ public: virtual status_t captureLayers(const sp& layerHandleBinder, sp* outBuffer, const Rect& sourceCrop, - float frameScale) { + float frameScale, bool childrenOnly) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); data.write(sourceCrop); data.writeFloat(frameScale); + data.writeBool(childrenOnly); status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); if (err != NO_ERROR) { @@ -629,8 +630,10 @@ status_t BnSurfaceComposer::onTransact( Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); float frameScale = data.readFloat(); + bool childrenOnly = data.readBool(); - status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale); + status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale, + childrenOnly); reply->writeInt32(res); if (res == NO_ERROR) { reply->write(*outBuffer); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 92a24ad933..0d7ffc3d71 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -751,7 +751,17 @@ status_t ScreenshotClient::captureLayers(const sp& layerHandle, Rect so float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale); + status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale, + false /* childrenOnly */); + return ret; +} + +status_t ScreenshotClient::captureChildLayers(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer) { + sp s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale, + true /* childrenOnly */); return ret; } // ---------------------------------------------------------------------------- diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index e26e332589..5ab64454e5 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -173,9 +173,12 @@ public: int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, Rotation rotation = eRotateNone) = 0; + /** + * Capture a subtree of the layer hierarchy, potentially ignoring the root node. + */ virtual status_t captureLayers(const sp& layerHandleBinder, sp* outBuffer, const Rect& sourceCrop, - float frameScale = 1.0) = 0; + float frameScale = 1.0, bool childrenOnly = false) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 3fe66356bf..fe46146ff5 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -297,8 +297,10 @@ public: uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, uint32_t rotation, sp* outBuffer); - static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float fameScale, + static status_t captureLayers(const sp& layerHandle, Rect sourceCrop, float frameScale, sp* outBuffer); + static status_t captureChildLayers(const sp& layerHandle, Rect sourceCrop, + float frameScale, sp* outBuffer); }; // --------------------------------------------------------------------------- diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 8060b6e7c5..4fb51e1b96 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -593,8 +593,8 @@ public: bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp& /*parentHandle*/, - sp* /*outBuffer*/, - const Rect& /*sourceCrop*/, float /*frameScale*/) override { + sp* /*outBuffer*/, const Rect& /*sourceCrop*/, + float /*frameScale*/, bool /*childrenOnly*/) override { return NO_ERROR; } status_t clearAnimationFrameStats() override { return NO_ERROR; } diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 2f89cc1d76..f259d93c3f 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -16,24 +16,24 @@ // #define LOG_NDEBUG 0 #undef LOG_TAG -#define LOG_TAG "AbstractLayer" +#define LOG_TAG "ContainerLayer" -#include "AbstractLayer.h" +#include "ContainerLayer.h" namespace android { -AbstractLayer::AbstractLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags) +ContainerLayer::ContainerLayer(SurfaceFlinger* flinger, const sp& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) : Layer(flinger, client, name, w, h, flags) { mDrawingState = mCurrentState; } -void AbstractLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) const {} +void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) const {} -bool AbstractLayer::isVisible() const { +bool ContainerLayer::isVisible() const { return !isHiddenByPolicy(); } -void AbstractLayer::setPerFrameData(const sp&) {} +void ContainerLayer::setPerFrameData(const sp&) {} } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 808ae3367d..543f60a624 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -23,13 +23,13 @@ namespace android { -class AbstractLayer : public Layer { +class ContainerLayer : public Layer { public: - AbstractLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags); - virtual ~AbstractLayer() = default; + ContainerLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags); + virtual ~ContainerLayer() = default; - const char* getTypeId() const override { return "AbstractLayer"; } + const char* getTypeId() const override { return "ContainerLayer"; } void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const override; bool isVisible() const override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 78dd40b32f..44e60edb37 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1594,6 +1594,12 @@ bool Layer::reparentChildren(const sp& newParentHandle) { return true; } +void Layer::reparentChildrenForDrawing(const sp& newParent) { + for (const sp& child : mDrawingChildren) { + child->mDrawingParent = newParent; + } +} + bool Layer::reparent(const sp& newParentHandle) { if (newParentHandle == nullptr) { return false; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ab004f2a6f..996d686371 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -287,7 +287,7 @@ public: bool setOverrideScalingMode(int32_t overrideScalingMode); void setInfo(uint32_t type, uint32_t appId); bool reparentChildren(const sp& layer); - bool reparentChildrenForDrawing(const sp& layer); + void reparentChildrenForDrawing(const sp& layer); bool reparent(const sp& newParentHandle); bool detachChildren(); diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index fa4df8360f..940a34ce1c 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -2,6 +2,8 @@ #include "Transform.h" +#include + namespace android { class RenderArea { @@ -22,6 +24,8 @@ public: virtual bool needsFiltering() const = 0; virtual Rect getSourceCrop() const = 0; + virtual void render(std::function drawLayers) { drawLayers(); } + int getReqHeight() const { return mReqHeight; }; int getReqWidth() const { return mReqWidth; }; Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cb410a14e1..38b93b110b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -61,20 +61,21 @@ #include #include +#include "BufferLayer.h" #include "Client.h" -#include "clz.h" +#include "ColorLayer.h" #include "Colorizer.h" +#include "ContainerLayer.h" #include "DdmConnection.h" -#include "DisplayDevice.h" #include "DispSync.h" +#include "DisplayDevice.h" #include "EventControlThread.h" #include "EventThread.h" #include "Layer.h" -#include "BufferLayer.h" #include "LayerVector.h" -#include "ColorLayer.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" +#include "clz.h" #include "DisplayHardware/ComposerHal.h" #include "DisplayHardware/FramebufferSurface.h" @@ -4418,19 +4419,18 @@ status_t SurfaceFlinger::captureScreen(const sp& display, sp& layerHandleBinder, sp* outBuffer, const Rect& sourceCrop, - float frameScale) { + float frameScale, bool childrenOnly) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: - LayerRenderArea(const sp& layer, const Rect crop, int32_t reqWidth, - int32_t reqHeight) - : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} - const Transform& getTransform() const override { - // Make the top level transform the inverse the transform and it's parent so it sets - // the whole capture back to 0,0 - return *new Transform(mLayer->getTransform().inverse()); - } + LayerRenderArea(SurfaceFlinger* flinger, const sp& layer, const Rect crop, + int32_t reqWidth, int32_t reqHeight, bool childrenOnly) + : RenderArea(reqHeight, reqWidth), + mLayer(layer), + mCrop(crop), + mFlinger(flinger), + mChildrenOnly(childrenOnly) {} Rect getBounds() const override { const Layer::State& layerState(mLayer->getDrawingState()); return Rect(layerState.active.w, layerState.active.h); @@ -4439,6 +4439,34 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, int getWidth() const override { return mLayer->getDrawingState().active.w; } bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } + const Transform& getTransform() const { return mTransform; } + + class ReparentForDrawing { + public: + const sp& oldParent; + const sp& newParent; + + ReparentForDrawing(const sp& oldParent, const sp& newParent) + : oldParent(oldParent), newParent(newParent) { + oldParent->reparentChildrenForDrawing(newParent); + } + ~ReparentForDrawing() { newParent->reparentChildrenForDrawing(oldParent); } + }; + + void render(std::function drawLayers) override { + if (!mChildrenOnly) { + mTransform = mLayer->getTransform().inverse(); + drawLayers(); + } else { + Rect bounds = getBounds(); + screenshotParentLayer = + new ContainerLayer(mFlinger, nullptr, String8("Screenshot Parent"), + bounds.getWidth(), bounds.getHeight(), 0); + + ReparentForDrawing reparent(mLayer, screenshotParentLayer); + drawLayers(); + } + } Rect getSourceCrop() const override { if (mCrop.isEmpty()) { @@ -4453,6 +4481,14 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, private: const sp mLayer; const Rect mCrop; + + // In the "childrenOnly" case we reparent the children to a screenshot + // layer which has no properties set and which does not draw. + sp screenshotParentLayer; + Transform mTransform; + + SurfaceFlinger* mFlinger; + const bool mChildrenOnly; }; auto layerHandle = reinterpret_cast(layerHandleBinder.get()); @@ -4463,6 +4499,13 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, return NAME_NOT_FOUND; } + const int uid = IPCThreadState::self()->getCallingUid(); + const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM; + if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) { + ALOGW("Attempting to capture secure layer: PERMISSION_DENIED"); + return PERMISSION_DENIED; + } + Rect crop(sourceCrop); if (sourceCrop.width() <= 0) { crop.left = 0; @@ -4477,12 +4520,14 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, int32_t reqWidth = crop.width() * frameScale; int32_t reqHeight = crop.height() * frameScale; - LayerRenderArea renderArea(parent, crop, reqWidth, reqHeight); + LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, childrenOnly); - auto traverseLayers = [parent](const LayerVector::Visitor& visitor) { + auto traverseLayers = [parent, childrenOnly](const LayerVector::Visitor& visitor) { parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { if (!layer->isVisible()) { return; + } else if (childrenOnly && layer == parent.get()) { + return; } visitor(layer); }); @@ -4529,8 +4574,10 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, int fd = -1; { Mutex::Autolock _l(mStateLock); - result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), - useIdentityTransform, forSystem, &fd); + renderArea.render([&]() { + result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(), + useIdentityTransform, forSystem, &fd); + }); } { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 392acaa0a6..33786e8558 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -387,7 +387,7 @@ private: int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation); virtual status_t captureLayers(const sp& parentHandle, sp* outBuffer, - const Rect& sourceCrop, float frameScale); + const Rect& sourceCrop, float frameScale, bool childrenOnly); virtual status_t getDisplayStats(const sp& display, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp& display, diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 92c26af9eb..fd219913df 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -192,6 +192,16 @@ public: *sc = std::make_unique(outBuffer); } + static void captureChildLayers(std::unique_ptr* sc, sp& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { + sp sf(ComposerService::getComposerService()); + SurfaceComposerClient::Transaction().apply(true); + + sp outBuffer; + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale, true)); + *sc = std::make_unique(outBuffer); + } + void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) { ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance); @@ -2306,6 +2316,74 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { mCapture->expectChildColor(0, 0); } +TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp child = + mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + + SurfaceComposerClient::Transaction().show(child).apply(true); + + // Captures mFGSurfaceControl's child + ScreenCapture::captureChildLayers(&mCapture, fgHandle); + mCapture->checkPixel(10, 10, 0, 0, 0); + mCapture->expectChildColor(0, 0); +} + + +// In the following tests we verify successful skipping of a parent layer, +// so we use the same verification logic and only change how we mutate +// the parent layer to verify that various properties are ignored. +class ScreenCaptureChildOnlyTest : public LayerUpdateTest { +public: + void SetUp() override { + LayerUpdateTest::SetUp(); + + mChild = + mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(mChild, 200, 200, 200); + + SurfaceComposerClient::Transaction().show(mChild).apply(true); + } + + void verify() { + auto fgHandle = mFGSurfaceControl->getHandle(); + ScreenCapture::captureChildLayers(&mCapture, fgHandle); + mCapture->checkPixel(10, 10, 0, 0, 0); + mCapture->expectChildColor(0, 0); + } + + std::unique_ptr mCapture; + sp mChild; +}; + +TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) { + + SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true); + + // Even though the parent is hidden we should still capture the child. + verify(); +} + +TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) { + + SurfaceComposerClient::Transaction().setCrop(mFGSurfaceControl, Rect(0, 0, 1, 1)).apply(true); + + // Even though the parent is cropped out we should still capture the child. + verify(); +} + +TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) { + + SurfaceComposerClient::Transaction().setMatrix(mFGSurfaceControl, 2, 0, 0, 2); + + // We should not inherit the parent scaling. + verify(); +} + TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { auto fgHandle = mFGSurfaceControl->getHandle(); -- cgit v1.2.3-59-g8ed1b From a52f0295622a42849f5ef81c44589b816b2ccacb Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 14 Mar 2018 17:26:31 -0700 Subject: [Native] Replace android_color_mode usage with ColorMode. To ease the pain when we add color mode v1.1, we replace all current android_color_mode usage in framework native with ColorMode directly from HAL. BUG: 73824924 Test: Build & flash Change-Id: I4436fc225c7807506825c7148bc794cb99f278dc --- libs/gui/Android.bp | 2 + libs/gui/ISurfaceComposer.cpp | 26 +++++----- libs/gui/Surface.cpp | 10 ++-- libs/gui/SurfaceComposerClient.cpp | 6 +-- libs/gui/include/gui/ISurfaceComposer.h | 7 +-- libs/gui/include/gui/SurfaceComposerClient.h | 7 +-- libs/gui/tests/Surface_test.cpp | 8 +-- libs/ui/DebugUtils.cpp | 43 ++++++++-------- libs/ui/include/ui/DebugUtils.h | 4 +- libs/ui/include/ui/GraphicsTypes.h | 26 ++++++++++ services/surfaceflinger/DisplayDevice.cpp | 6 +-- services/surfaceflinger/DisplayDevice.h | 9 ++-- services/surfaceflinger/DisplayHardware/HWC2.cpp | 11 ++-- services/surfaceflinger/DisplayHardware/HWC2.h | 5 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 8 +-- .../surfaceflinger/DisplayHardware/HWComposer.h | 5 +- services/surfaceflinger/RenderArea.h | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 58 +++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 10 ++-- services/surfaceflinger/layerproto/Android.bp | 1 + services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 46 +++++++++-------- 21 files changed, 170 insertions(+), 132 deletions(-) create mode 100644 libs/ui/include/ui/GraphicsTypes.h (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index a1a0928154..2768ad8560 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -122,6 +122,7 @@ cc_library_shared { ], shared_libs: [ + "android.hardware.graphics.common@1.1", "libsync", "libbinder", "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui. @@ -154,6 +155,7 @@ cc_library_shared { "libui", "android.hidl.token@1.0-utils", "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.common@1.1", ], export_header_lib_headers: [ diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index beda778396..0244bb512e 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -350,7 +350,7 @@ public: } virtual status_t getDisplayColorModes(const sp& display, - Vector* outColorModes) { + Vector* outColorModes) { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -373,34 +373,34 @@ public: outColorModes->clear(); outColorModes->resize(numModes); for (size_t i = 0; i < numModes; ++i) { - outColorModes->replaceAt(static_cast(reply.readInt32()), i); + outColorModes->replaceAt(static_cast(reply.readInt32()), i); } } return result; } - virtual android_color_mode_t getActiveColorMode(const sp& display) { + virtual ColorMode getActiveColorMode(const sp& display) { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { ALOGE("getActiveColorMode failed to writeInterfaceToken: %d", result); - return static_cast(result); + return static_cast(result); } result = data.writeStrongBinder(display); if (result != NO_ERROR) { ALOGE("getActiveColorMode failed to writeStrongBinder: %d", result); - return static_cast(result); + return static_cast(result); } result = remote()->transact(BnSurfaceComposer::GET_ACTIVE_COLOR_MODE, data, &reply); if (result != NO_ERROR) { ALOGE("getActiveColorMode failed to transact: %d", result); - return static_cast(result); + return static_cast(result); } - return static_cast(reply.readInt32()); + return static_cast(reply.readInt32()); } virtual status_t setActiveColorMode(const sp& display, - android_color_mode_t colorMode) { + ColorMode colorMode) { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -412,7 +412,7 @@ public: ALOGE("setActiveColorMode failed to writeStrongBinder: %d", result); return result; } - result = data.writeInt32(colorMode); + result = data.writeInt32(static_cast(colorMode)); if (result != NO_ERROR) { ALOGE("setActiveColorMode failed to writeInt32: %d", result); return result; @@ -739,7 +739,7 @@ status_t BnSurfaceComposer::onTransact( } case GET_DISPLAY_COLOR_MODES: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - Vector colorModes; + Vector colorModes; sp display = nullptr; status_t result = data.readStrongBinder(&display); if (result != NO_ERROR) { @@ -751,7 +751,7 @@ status_t BnSurfaceComposer::onTransact( if (result == NO_ERROR) { reply->writeUint32(static_cast(colorModes.size())); for (size_t i = 0; i < colorModes.size(); ++i) { - reply->writeInt32(colorModes[i]); + reply->writeInt32(static_cast(colorModes[i])); } } return NO_ERROR; @@ -764,7 +764,7 @@ status_t BnSurfaceComposer::onTransact( ALOGE("getActiveColorMode failed to readStrongBinder: %d", result); return result; } - android_color_mode_t colorMode = getActiveColorMode(display); + ColorMode colorMode = getActiveColorMode(display); result = reply->writeInt32(static_cast(colorMode)); return result; } @@ -783,7 +783,7 @@ status_t BnSurfaceComposer::onTransact( return result; } result = setActiveColorMode(display, - static_cast(colorModeInt)); + static_cast(colorModeInt)); result = reply->writeInt32(result); return result; } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e08d6b0bae..2e1c24b755 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -326,7 +326,7 @@ status_t Surface::getWideColorSupport(bool* supported) { sp display( composerService()->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); - Vector colorModes; + Vector colorModes; status_t err = composerService()->getDisplayColorModes(display, &colorModes); @@ -338,11 +338,11 @@ status_t Surface::getWideColorSupport(bool* supported) { &ISurfaceFlingerConfigs::hasWideColorDisplay>(false); *supported = false; - for (android_color_mode_t colorMode : colorModes) { + for (ColorMode colorMode : colorModes) { switch (colorMode) { - case HAL_COLOR_MODE_DISPLAY_P3: - case HAL_COLOR_MODE_ADOBE_RGB: - case HAL_COLOR_MODE_DCI_P3: + case ColorMode::DISPLAY_P3: + case ColorMode::ADOBE_RGB: + case ColorMode::DCI_P3: if (wideColorBoardConfig) { *supported = true; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0d7ffc3d71..61ed976fcc 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -698,16 +698,16 @@ status_t SurfaceComposerClient::setActiveConfig(const sp& display, int } status_t SurfaceComposerClient::getDisplayColorModes(const sp& display, - Vector* outColorModes) { + Vector* outColorModes) { return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes); } -android_color_mode_t SurfaceComposerClient::getActiveColorMode(const sp& display) { +ColorMode SurfaceComposerClient::getActiveColorMode(const sp& display) { return ComposerService::getComposerService()->getActiveColorMode(display); } status_t SurfaceComposerClient::setActiveColorMode(const sp& display, - android_color_mode_t colorMode) { + ColorMode colorMode) { return ComposerService::getComposerService()->setActiveColorMode(display, colorMode); } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 5ab64454e5..afe9358c0a 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -160,10 +161,10 @@ public: virtual status_t setActiveConfig(const sp& display, int id) = 0; virtual status_t getDisplayColorModes(const sp& display, - Vector* outColorModes) = 0; - virtual android_color_mode_t getActiveColorMode(const sp& display) = 0; + Vector* outColorModes) = 0; + virtual ColorMode getActiveColorMode(const sp& display) = 0; virtual status_t setActiveColorMode(const sp& display, - android_color_mode_t colorMode) = 0; + ColorMode colorMode) = 0; /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index fe46146ff5..162fe6e4e6 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -88,13 +89,13 @@ public: // Gets the list of supported color modes for the given display static status_t getDisplayColorModes(const sp& display, - Vector* outColorModes); + Vector* outColorModes); // Gets the active color mode for the given display - static android_color_mode_t getActiveColorMode(const sp& display); + static ColorMode getActiveColorMode(const sp& display); // Sets the active color mode for the given display - static status_t setActiveColorMode(const sp& display, android_color_mode_t colorMode); + static status_t setActiveColorMode(const sp& display, ColorMode colorMode); /* Triggers screen on/off or low power mode and waits for it to complete */ static void setDisplayPowerMode(const sp& display, int mode); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 4fb51e1b96..66d5595fb9 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -577,15 +577,15 @@ public: return NO_ERROR; } status_t getDisplayColorModes(const sp& /*display*/, - Vector* /*outColorModes*/) override { + Vector* /*outColorModes*/) override { return NO_ERROR; } - android_color_mode_t getActiveColorMode(const sp& /*display*/) + ColorMode getActiveColorMode(const sp& /*display*/) override { - return HAL_COLOR_MODE_NATIVE; + return ColorMode::NATIVE; } status_t setActiveColorMode(const sp& /*display*/, - android_color_mode_t /*colorMode*/) override { return NO_ERROR; } + ColorMode /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp& /*display*/, sp* /*outBuffer*/, Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp index 17ebf80329..d7e191db89 100644 --- a/libs/ui/DebugUtils.cpp +++ b/libs/ui/DebugUtils.cpp @@ -22,6 +22,7 @@ #include using android::base::StringPrintf; +using android::ColorMode; std::string decodeStandard(android_dataspace dataspace) { const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK); @@ -197,37 +198,37 @@ std::string dataspaceDetails(android_dataspace dataspace) { decodeRange(dataspace).c_str()); } -std::string decodeColorMode(android_color_mode colorMode) { +std::string decodeColorMode(ColorMode colorMode) { switch (colorMode) { - case HAL_COLOR_MODE_NATIVE: - return std::string("HAL_COLOR_MODE_NATIVE"); + case ColorMode::NATIVE: + return std::string("ColorMode::NATIVE"); - case HAL_COLOR_MODE_STANDARD_BT601_625: - return std::string("HAL_COLOR_MODE_BT601_625"); + case ColorMode::STANDARD_BT601_625: + return std::string("ColorMode::BT601_625"); - case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED: - return std::string("HAL_COLOR_MODE_BT601_625_UNADJUSTED"); + case ColorMode::STANDARD_BT601_625_UNADJUSTED: + return std::string("ColorMode::BT601_625_UNADJUSTED"); - case HAL_COLOR_MODE_STANDARD_BT601_525: - return std::string("HAL_COLOR_MODE_BT601_525"); + case ColorMode::STANDARD_BT601_525: + return std::string("ColorMode::BT601_525"); - case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED: - return std::string("HAL_COLOR_MODE_BT601_525_UNADJUSTED"); + case ColorMode::STANDARD_BT601_525_UNADJUSTED: + return std::string("ColorMode::BT601_525_UNADJUSTED"); - case HAL_COLOR_MODE_STANDARD_BT709: - return std::string("HAL_COLOR_MODE_BT709"); + case ColorMode::STANDARD_BT709: + return std::string("ColorMode::BT709"); - case HAL_COLOR_MODE_DCI_P3: - return std::string("HAL_COLOR_MODE_DCI_P3"); + case ColorMode::DCI_P3: + return std::string("ColorMode::DCI_P3"); - case HAL_COLOR_MODE_SRGB: - return std::string("HAL_COLOR_MODE_SRGB"); + case ColorMode::SRGB: + return std::string("ColorMode::SRGB"); - case HAL_COLOR_MODE_ADOBE_RGB: - return std::string("HAL_COLOR_MODE_ADOBE_RGB"); + case ColorMode::ADOBE_RGB: + return std::string("ColorMode::ADOBE_RGB"); - case HAL_COLOR_MODE_DISPLAY_P3: - return std::string("HAL_COLOR_MODE_DISPLAY_P3"); + case ColorMode::DISPLAY_P3: + return std::string("ColorMode::DISPLAY_P3"); } return android::base::StringPrintf("Unknown color mode %d", colorMode); diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h index dad9446b3a..33701070a9 100644 --- a/libs/ui/include/ui/DebugUtils.h +++ b/libs/ui/include/ui/DebugUtils.h @@ -16,7 +16,7 @@ #pragma once -#include +#include #include #include @@ -29,6 +29,6 @@ std::string decodeStandard(android_dataspace dataspace); std::string decodeTransfer(android_dataspace dataspace); std::string decodeRange(android_dataspace dataspace); std::string dataspaceDetails(android_dataspace dataspace); -std::string decodeColorMode(android_color_mode colormode); +std::string decodeColorMode(android::ColorMode colormode); std::string decodePixelFormat(android::PixelFormat format); std::string to_string(const android::Rect& rect); diff --git a/libs/ui/include/ui/GraphicsTypes.h b/libs/ui/include/ui/GraphicsTypes.h new file mode 100644 index 0000000000..fa9a812d97 --- /dev/null +++ b/libs/ui/include/ui/GraphicsTypes.h @@ -0,0 +1,26 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace android { + +using android::hardware::graphics::common::V1_0::ColorMode; + +} // namespace android diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index d40666e6f1..92d5e21f34 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -99,7 +99,7 @@ DisplayDevice::DisplayDevice( mNativeWindow = surface = new Surface(producer, false); ANativeWindow* const window = mNativeWindow.get(); - mActiveColorMode = HAL_COLOR_MODE_NATIVE; + mActiveColorMode = ColorMode::NATIVE; mDisplayHasWideColor = supportWideColor; mDisplayHasHdr = supportHdr; @@ -292,11 +292,11 @@ int DisplayDevice::getActiveConfig() const { } // ---------------------------------------------------------------------------- -void DisplayDevice::setActiveColorMode(android_color_mode_t mode) { +void DisplayDevice::setActiveColorMode(ColorMode mode) { mActiveColorMode = mode; } -android_color_mode_t DisplayDevice::getActiveColorMode() const { +ColorMode DisplayDevice::getActiveColorMode() const { return mActiveColorMode; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index d5ed15fa28..737971f83d 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -31,6 +31,7 @@ #include #include +#include #include "RenderArea.h" #include "RenderEngine/Surface.h" @@ -155,8 +156,8 @@ public: void setPowerMode(int mode); bool isDisplayOn() const; - android_color_mode_t getActiveColorMode() const; - void setActiveColorMode(android_color_mode_t mode); + ColorMode getActiveColorMode() const; + void setActiveColorMode(ColorMode mode); void setCompositionDataSpace(android_dataspace dataspace); /* ------------------------------------------------------------------------ @@ -230,7 +231,7 @@ private: // Current active config int mActiveConfig; // current active color mode - android_color_mode_t mActiveColorMode; + ColorMode mActiveColorMode; // Need to know if display is wide-color capable or not. // Initialized by SurfaceFlinger when the DisplayDevice is created. @@ -279,7 +280,7 @@ public: bool needsFiltering() const override { return mDevice->needsFiltering(); } Rect getSourceCrop() const override { return mSourceCrop; } bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); } - android_color_mode_t getActiveColorMode() const override { + ColorMode getActiveColorMode() const override { return mDevice->getActiveColorMode(); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index f14c2fe10b..b7bf964f29 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -362,9 +362,9 @@ Error Display::getChangedCompositionTypes( return Error::None; } -Error Display::getColorModes(std::vector* outModes) const +Error Display::getColorModes(std::vector* outModes) const { - std::vector modes; + std::vector modes; auto intError = mComposer.getColorModes(mId, &modes); uint32_t numModes = modes.size(); auto error = static_cast(intError); @@ -374,7 +374,7 @@ Error Display::getColorModes(std::vector* outModes) const outModes->resize(numModes); for (size_t i = 0; i < numModes; i++) { - (*outModes)[i] = static_cast(modes[i]); + (*outModes)[i] = modes[i]; } return Error::None; } @@ -537,10 +537,9 @@ Error Display::setClientTarget(uint32_t slot, const sp& target, return static_cast(intError); } -Error Display::setColorMode(android_color_mode_t mode) +Error Display::setColorMode(android::ColorMode mode) { - auto intError = mComposer.setColorMode( - mId, static_cast(mode)); + auto intError = mComposer.setColorMode(mId, mode); return static_cast(intError); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index e74f00dccc..0fc37ece56 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -209,7 +210,7 @@ public: [[clang::warn_unused_result]] Error getChangedCompositionTypes( std::unordered_map* outTypes); [[clang::warn_unused_result]] Error getColorModes( - std::vector* outModes) const; + std::vector* outModes) const; // Doesn't call into the HWC2 device, so no errors are possible std::vector> getConfigs() const; @@ -233,7 +234,7 @@ public: uint32_t slot, const android::sp& target, const android::sp& acquireFence, android_dataspace_t dataspace); - [[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode); + [[clang::warn_unused_result]] Error setColorMode(android::ColorMode mode); [[clang::warn_unused_result]] Error setColorTransform( const android::mat4& matrix, android_color_transform_t hint); [[clang::warn_unused_result]] Error setOutputBuffer( diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 2cafd8e9f9..6d5917db2f 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -311,8 +311,8 @@ std::shared_ptr return config; } -std::vector HWComposer::getColorModes(int32_t displayId) const { - std::vector modes; +std::vector HWComposer::getColorModes(int32_t displayId) const { + std::vector modes; if (!isValidDisplay(displayId)) { ALOGE("getColorModes: Attempted to access invalid display %d", @@ -324,13 +324,13 @@ std::vector HWComposer::getColorModes(int32_t displayId) c if (error != HWC2::Error::None) { ALOGE("getColorModes failed for display %d: %s (%d)", displayId, to_string(error).c_str(), static_cast(error)); - return std::vector(); + return std::vector(); } return modes; } -status_t HWComposer::setActiveColorMode(int32_t displayId, android_color_mode_t mode) { +status_t HWComposer::setActiveColorMode(int32_t displayId, ColorMode mode) { if (!isValidDisplay(displayId)) { ALOGE("setActiveColorMode: Display %d is not valid", displayId); return BAD_INDEX; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index b75dc6adf7..c442b2f191 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -158,9 +159,9 @@ public: std::shared_ptr getActiveConfig(int32_t displayId) const; - std::vector getColorModes(int32_t displayId) const; + std::vector getColorModes(int32_t displayId) const; - status_t setActiveColorMode(int32_t displayId, android_color_mode_t mode); + status_t setActiveColorMode(int32_t displayId, ColorMode mode); bool isUsingVrComposer() const; diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 940a34ce1c..b9c4909d5a 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "Transform.h" #include @@ -30,7 +32,7 @@ public: int getReqWidth() const { return mReqWidth; }; Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; virtual bool getWideColorSupport() const = 0; - virtual android_color_mode_t getActiveColorMode() const = 0; + virtual ColorMode getActiveColorMode() const = 0; status_t updateDimensions(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 38b93b110b..5dd5d7c9f2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -913,7 +913,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp& display, int mode) { return NO_ERROR; } status_t SurfaceFlinger::getDisplayColorModes(const sp& display, - Vector* outColorModes) { + Vector* outColorModes) { if ((outColorModes == nullptr) || (display.get() == nullptr)) { return BAD_VALUE; } @@ -934,7 +934,7 @@ status_t SurfaceFlinger::getDisplayColorModes(const sp& display, return type; } - std::vector modes; + std::vector modes; { ConditionalLock _l(mStateLock, std::this_thread::get_id() != mMainThreadId); @@ -946,18 +946,18 @@ status_t SurfaceFlinger::getDisplayColorModes(const sp& display, return NO_ERROR; } -android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp& display) { +ColorMode SurfaceFlinger::getActiveColorMode(const sp& display) { sp device(getDisplayDevice(display)); if (device != nullptr) { return device->getActiveColorMode(); } - return static_cast(BAD_VALUE); + return static_cast(BAD_VALUE); } void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, - android_color_mode_t mode) { + ColorMode mode) { int32_t type = hw->getDisplayType(); - android_color_mode_t currentMode = hw->getActiveColorMode(); + ColorMode currentMode = hw->getActiveColorMode(); if (mode == currentMode) { return; @@ -977,20 +977,20 @@ void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, status_t SurfaceFlinger::setActiveColorMode(const sp& display, - android_color_mode_t colorMode) { + ColorMode colorMode) { class MessageSetActiveColorMode: public MessageBase { SurfaceFlinger& mFlinger; sp mDisplay; - android_color_mode_t mMode; + ColorMode mMode; public: MessageSetActiveColorMode(SurfaceFlinger& flinger, const sp& disp, - android_color_mode_t mode) : + ColorMode mode) : mFlinger(flinger), mDisplay(disp) { mMode = mode; } virtual bool handler() { - Vector modes; + Vector modes; mFlinger.getDisplayColorModes(mDisplay, &modes); bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes); - if (mMode < 0 || !exists) { + if (mMode < ColorMode::NATIVE || !exists) { ALOGE("Attempt to set invalid active color mode %s (%d) for display %p", decodeColorMode(mMode).c_str(), mMode, mDisplay.get()); return true; @@ -1783,9 +1783,9 @@ mat4 SurfaceFlinger::computeSaturationMatrix() const { // pickColorMode translates a given dataspace into the best available color mode. // Currently only support sRGB and Display-P3. -android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const { +ColorMode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const { if (mForceNativeColorMode) { - return HAL_COLOR_MODE_NATIVE; + return ColorMode::NATIVE; } switch (dataSpace) { @@ -1794,18 +1794,18 @@ android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) co case HAL_DATASPACE_UNKNOWN: case HAL_DATASPACE_SRGB: case HAL_DATASPACE_V0_SRGB: - return HAL_COLOR_MODE_SRGB; + return ColorMode::SRGB; break; case HAL_DATASPACE_DISPLAY_P3: - return HAL_COLOR_MODE_DISPLAY_P3; + return ColorMode::DISPLAY_P3; break; default: // TODO (courtneygo): Do we want to assert an error here? ALOGE("No color mode mapping for %s (%#x)", dataspaceDetails(dataSpace).c_str(), dataSpace); - return HAL_COLOR_MODE_SRGB; + return ColorMode::SRGB; break; } } @@ -1927,7 +1927,7 @@ void SurfaceFlinger::setUpHWComposer() { } if (hasWideColorDisplay) { - android_color_mode newColorMode; + ColorMode newColorMode; android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB; for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { @@ -2269,13 +2269,13 @@ void SurfaceFlinger::processDisplayChangesLocked() { if (dispSurface != nullptr) { bool hasWideColorSupport = false; if (hasWideColorDisplay) { - std::vector modes = + std::vector modes = getHwComposer().getColorModes(state.type); - for (android_color_mode_t colorMode : modes) { + for (ColorMode colorMode : modes) { switch (colorMode) { - case HAL_COLOR_MODE_DISPLAY_P3: - case HAL_COLOR_MODE_ADOBE_RGB: - case HAL_COLOR_MODE_DCI_P3: + case ColorMode::DISPLAY_P3: + case ColorMode::ADOBE_RGB: + case ColorMode::DCI_P3: hasWideColorSupport = true; break; default: @@ -2298,9 +2298,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { dispSurface, producer, hasWideColorSupport, hasHdrSupport); - android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE; + ColorMode defaultColorMode = ColorMode::NATIVE; if (hasWideColorSupport) { - defaultColorMode = HAL_COLOR_MODE_SRGB; + defaultColorMode = ColorMode::SRGB; } setActiveColorModeInternal(hw, defaultColorMode); hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN); @@ -2741,7 +2741,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN; if (displayDevice->getWideColorSupport() && - displayDevice->getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) { + displayDevice->getActiveColorMode() == ColorMode::DISPLAY_P3) { outputDataspace = HAL_DATASPACE_DISPLAY_P3; } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); @@ -3879,12 +3879,12 @@ void SurfaceFlinger::dumpWideColorInfo(String8& result) const { } result.appendFormat("Display %d color modes:\n", hwcId); - std::vector modes = getHwComposer().getColorModes(hwcId); + std::vector modes = getHwComposer().getColorModes(hwcId); for (auto&& mode : modes) { result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode); } - android_color_mode_t currentMode = displayDevice->getActiveColorMode(); + ColorMode currentMode = displayDevice->getActiveColorMode(); result.appendFormat(" Current color mode: %s (%d)\n", decodeColorMode(currentMode).c_str(), currentMode); } @@ -4476,7 +4476,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, } } bool getWideColorSupport() const override { return false; } - android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; } + ColorMode getActiveColorMode() const override { return ColorMode::NATIVE; } private: const sp mLayer; @@ -4650,7 +4650,7 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN; if (renderArea.getWideColorSupport() && - renderArea.getActiveColorMode() == HAL_COLOR_MODE_DISPLAY_P3) { + renderArea.getActiveColorMode() == ColorMode::DISPLAY_P3) { outputDataspace = HAL_DATASPACE_DISPLAY_P3; } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 33786e8558..104adef4d3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -394,9 +394,9 @@ private: Vector* configs); virtual int getActiveConfig(const sp& display); virtual status_t getDisplayColorModes(const sp& display, - Vector* configs); - virtual android_color_mode_t getActiveColorMode(const sp& display); - virtual status_t setActiveColorMode(const sp& display, android_color_mode_t colorMode); + Vector* configs); + virtual ColorMode getActiveColorMode(const sp& display); + virtual status_t setActiveColorMode(const sp& display, ColorMode colorMode); virtual void setPowerMode(const sp& display, int mode); virtual status_t setActiveConfig(const sp& display, int id); virtual status_t clearAnimationFrameStats(); @@ -446,7 +446,7 @@ private: bool stateLockHeld); // Called on the main thread in response to setActiveColorMode() - void setActiveColorModeInternal(const sp& hw, android_color_mode_t colorMode); + void setActiveColorModeInternal(const sp& hw, ColorMode colorMode); // Returns whether the transaction actually modified any state bool handleMessageTransaction(); @@ -619,7 +619,7 @@ private: // Given a dataSpace, returns the appropriate color_mode to use // to display that dataSpace. - android_color_mode pickColorMode(android_dataspace dataSpace) const; + ColorMode pickColorMode(android_dataspace dataSpace) const; android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b, bool hasHdr) const; diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp index 485090c778..ac147fe182 100644 --- a/services/surfaceflinger/layerproto/Android.bp +++ b/services/surfaceflinger/layerproto/Android.bp @@ -10,6 +10,7 @@ cc_library_shared { ], shared_libs: [ + "android.hardware.graphics.common@1.1", "libui", "libprotobuf-cpp-lite", "libbase", diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 4878c140ed..86e2e1ec30 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #define HWC2_INCLUDE_STRINGIFICATION #define HWC2_USE_CPP11 @@ -34,6 +35,8 @@ #include "Hwc2TestClientTarget.h" #include "Hwc2TestVirtualDisplay.h" +using android::ColorMode; + void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData, @@ -865,7 +868,7 @@ public: } void getColorModes(hwc2_display_t display, - std::vector* outColorModes, + std::vector* outColorModes, hwc2_error_t* outErr = nullptr) { auto pfn = reinterpret_cast( @@ -892,7 +895,7 @@ public: } } - void setColorMode(hwc2_display_t display, android_color_mode_t colorMode, + void setColorMode(hwc2_display_t display, ColorMode colorMode, hwc2_error_t* outErr = nullptr) { auto pfn = reinterpret_cast( @@ -905,7 +908,7 @@ public: *outErr = err; } else { ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color mode " - << colorMode; + << static_cast(colorMode); } } @@ -4252,33 +4255,33 @@ TEST_F(Hwc2Test, GET_RELEASE_FENCES_bad_display) EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; } -static const std::array androidColorModes = {{ - HAL_COLOR_MODE_NATIVE, - HAL_COLOR_MODE_STANDARD_BT601_625, - HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED, - HAL_COLOR_MODE_STANDARD_BT601_525, - HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED, - HAL_COLOR_MODE_STANDARD_BT709, - HAL_COLOR_MODE_DCI_P3, - HAL_COLOR_MODE_SRGB, - HAL_COLOR_MODE_ADOBE_RGB, +static const std::array androidColorModes = {{ + ColorMode::NATIVE, + ColorMode::STANDARD_BT601_625, + ColorMode::STANDARD_BT601_625_UNADJUSTED, + ColorMode::STANDARD_BT601_525, + ColorMode::STANDARD_BT601_525_UNADJUSTED, + ColorMode::STANDARD_BT709, + ColorMode::DCI_P3, + ColorMode::SRGB, + ColorMode::ADOBE_RGB, }}; /* TESTCASE: Tests that the HWC2 can get the color modes for a display. The - * display must support HAL_COLOR_MODE_NATIVE */ + * display must support ColorMode::NATIVE */ TEST_F(Hwc2Test, GET_COLOR_MODES) { ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( [] (Hwc2Test* test, hwc2_display_t display) { - std::vector colorModes; + std::vector colorModes; ASSERT_NO_FATAL_FAILURE(test->getColorModes(display, &colorModes)); EXPECT_NE(std::count(colorModes.begin(), colorModes.end(), - HAL_COLOR_MODE_NATIVE), 0) << "all displays" - " must support HAL_COLOR_MODE_NATIVE"; + ColorMode::NATIVE), 0) << "all displays" + " must support ColorMode::NATIVE"; } )); } @@ -4287,7 +4290,7 @@ TEST_F(Hwc2Test, GET_COLOR_MODES) TEST_F(Hwc2Test, GET_COLOR_MODES_bad_display) { hwc2_display_t display; - std::vector colorModes; + std::vector colorModes; hwc2_error_t err = HWC2_ERROR_NONE; ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); @@ -4302,7 +4305,7 @@ TEST_F(Hwc2Test, SET_COLOR_MODES) ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( [] (Hwc2Test* test, hwc2_display_t display) { - const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE; + const ColorMode colorMode = ColorMode::NATIVE; EXPECT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode)); } @@ -4313,7 +4316,7 @@ TEST_F(Hwc2Test, SET_COLOR_MODES) TEST_F(Hwc2Test, SET_COLOR_MODES_bad_display) { hwc2_display_t display; - const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE; + const ColorMode colorMode = ColorMode::NATIVE; hwc2_error_t err = HWC2_ERROR_NONE; ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); @@ -4328,8 +4331,7 @@ TEST_F(Hwc2Test, SET_COLOR_MODES_bad_parameter) ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( [] (Hwc2Test* test, hwc2_display_t display) { - const android_color_mode_t colorMode = - static_cast(-1); + const ColorMode colorMode = static_cast(-1); hwc2_error_t err = HWC2_ERROR_NONE; ASSERT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode, -- cgit v1.2.3-59-g8ed1b From 0a0158c25c74de41770a9fa2f8d7da234a0dacee Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Fri, 16 Mar 2018 13:38:54 -0700 Subject: SF: Add IGBP list leak debugging info Adds a few things intended to make debugging IGBP list leaks easier: 1) A dumpsys line listing the current and max occupancies of the list 2) A debug property to set the max: debug.sf.max_igbp_list_size 3) Printing the current number of Layers when aborting Since we still have an unknown leak, this also sets the default limit four times higher to avoid hitting it in dogfood/automation. Bug: 74616334 Test: Manual, set max to 100 and verify above behaviors Change-Id: I7a6227a1d6fc05c197ec632db7dd9f875c64c6c9 --- services/surfaceflinger/SurfaceFlinger.cpp | 14 ++++++++++++-- services/surfaceflinger/SurfaceFlinger.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5dd5d7c9f2..282957fc68 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -260,6 +260,11 @@ SurfaceFlinger::SurfaceFlinger() mLayerTripleBufferingDisabled = atoi(value); ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering"); + // TODO (b/74616334): Reduce the default value once we isolate the leak + const size_t defaultListSize = 4 * MAX_LAYERS; + auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize)); + mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize; + // We should be reading 'persist.sys.sf.color_saturation' here // but since /data may be encrypted, we need to wait until after vold // comes online to attempt to read the property. The property is @@ -2896,8 +2901,11 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, } mGraphicBufferProducerList.insert(IInterface::asBinder(gbc).get()); - LOG_ALWAYS_FATAL_IF(mGraphicBufferProducerList.size() > MAX_LAYERS, - "Suspected IGBP leak"); + // TODO (b/74616334): Change this back to a fatal assert once the leak is fixed + ALOGE_IF(mGraphicBufferProducerList.size() > mMaxGraphicBufferProducerListSize, + "Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers", + mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize, + mNumLayers); mLayersAdded = true; mNumLayers++; } @@ -3966,6 +3974,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, */ colorizer.bold(result); result.appendFormat("Visible layers (count = %zu)\n", mNumLayers); + result.appendFormat("GraphicBufferProducers: %zu, max %zu\n", + mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize); colorizer.reset(result); LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 104adef4d3..51001e599d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -720,6 +720,7 @@ private: // Can't be unordered_set because wp<> isn't hashable std::set> mGraphicBufferProducerList; + size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS; // protected by mStateLock (but we could use another lock) bool mLayersRemoved; -- cgit v1.2.3-59-g8ed1b From 3b1b8affbda97b8414c3015648d7804609f727e6 Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Fri, 16 Mar 2018 17:37:33 -0700 Subject: Add a null check in case device disappears. This is a race condition possible when the caller get display IBinder the display is still here, but when it tries to take screenshot with that display, the display disappeared before it. Bug: 75324434 Test: smoke tests on walleye. This is a race so hard to verify. Change-Id: I5a107862e0b442840038b0956736e9661f556a23 --- services/surfaceflinger/SurfaceFlinger.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cb410a14e1..588cb2ab1a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4409,6 +4409,8 @@ status_t SurfaceFlinger::captureScreen(const sp& display, sp device(getDisplayDeviceLocked(display)); + if (CC_UNLIKELY(device == 0)) return BAD_VALUE; + DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation); auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, -- cgit v1.2.3-59-g8ed1b From 3bed0524e31f5f1844909006d952ff72196b98a2 Mon Sep 17 00:00:00 2001 From: Steven Thomas Date: Tue, 20 Mar 2018 15:40:48 -0700 Subject: Fix frozen screen after exiting vr When a hotplug connected event occurs, don't recreate any already-existing entries in mBuiltinDisplays. This fixes a problem where the screen would freeze after exiting vr. In the future, we may want to use hotplug connected events to notify surface flinger to reinitialize display state. This CL includes a change to the code in HWC2.cpp to always reinitialize the display state when we get a hotplug connected event, even if the display is already connected. Bug: 74985350 Test: - Confirmed exiting vr no longer freezes the screen. - Added code to simulate a hotplug connected event while the device is running, to test the changes in HWC2.cpp. Confirmed the device continued to function normally. Change-Id: I6afda67cae84842b2568c773e6b5aa4f38df6a96 Merged-In: I6afda67cae84842b2568c773e6b5aa4f38df6a96 --- services/surfaceflinger/DisplayHardware/HWC2.cpp | 46 ++++++++++++------------ services/surfaceflinger/SurfaceFlinger.cpp | 20 +++++------ 2 files changed, 33 insertions(+), 33 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index b7bf964f29..47f4e46361 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -144,31 +144,31 @@ void Device::destroyDisplay(hwc2_display_t displayId) 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( - &displayType)); - auto error = static_cast(intError); - if (error != Error::None) { - ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). " - "Aborting hotplug attempt.", - displayId, to_string(error).c_str(), intError); - return; - } + // If we get a hotplug connected event for a display we already have, + // destroy the display and recreate it. This will force us to requery + // the display params and recreate all layers on that display. + auto oldDisplay = getDisplayById(displayId); + if (oldDisplay != nullptr && oldDisplay->isConnected()) { + ALOGI("Hotplug connecting an already connected display." + " Clearing old display state."); + } + mDisplays.erase(displayId); - auto newDisplay = std::make_unique( - *mComposer.get(), mCapabilities, displayId, displayType); - mDisplays.emplace(displayId, std::move(newDisplay)); + DisplayType displayType; + auto intError = mComposer->getDisplayType(displayId, + reinterpret_cast( + &displayType)); + auto error = static_cast(intError); + if (error != Error::None) { + ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). " + "Aborting hotplug attempt.", + displayId, to_string(error).c_str(), intError); + return; } + + auto newDisplay = std::make_unique( + *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. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 11658e8b49..7e02922405 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2120,16 +2120,16 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { getBE().mHwc->onHotplug(event.display, displayType, event.connection); if (event.connection == HWC2::Connection::Connected) { - ALOGV("Creating built in display %d", displayType); - ALOGW_IF(mBuiltinDisplays[displayType], - "Overwriting display token for display type %d", displayType); - mBuiltinDisplays[displayType] = new BBinder(); - // All non-virtual displays are currently considered secure. - DisplayDeviceState info(displayType, true); - info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ? - "Built-in Screen" : "External Screen"; - mCurrentState.displays.add(mBuiltinDisplays[displayType], info); - mInterceptor.saveDisplayCreation(info); + if (!mBuiltinDisplays[displayType].get()) { + ALOGV("Creating built in display %d", displayType); + mBuiltinDisplays[displayType] = new BBinder(); + // All non-virtual displays are currently considered secure. + DisplayDeviceState info(displayType, true); + info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ? + "Built-in Screen" : "External Screen"; + mCurrentState.displays.add(mBuiltinDisplays[displayType], info); + mInterceptor.saveDisplayCreation(info); + } } else { ALOGV("Removing built in display %d", displayType); -- cgit v1.2.3-59-g8ed1b From 15eae09ebb293135dedce203bcb542a2e6e8d43a Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Fri, 23 Mar 2018 13:43:53 -0700 Subject: SurfaceFlinger: Fix reparenting following ReparentForDrawing Counterintuitively, the new-parent doesn't have the children in it's child list so even when cleaning up we need to call reparentChildrenForDrawing on the old parent instead of the new parent. Also clarify name to make this more obvious and add test. Test: Transaction_test.cpp Bug: 76099859 Change-Id: I935eec303dba320b5a2731606ec862311c5ca43e --- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 4 ++-- services/surfaceflinger/tests/Transaction_test.cpp | 11 +++++++++++ 4 files changed, 15 insertions(+), 4 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 44e60edb37..699c85caf9 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1594,7 +1594,7 @@ bool Layer::reparentChildren(const sp& newParentHandle) { return true; } -void Layer::reparentChildrenForDrawing(const sp& newParent) { +void Layer::setChildrenDrawingParent(const sp& newParent) { for (const sp& child : mDrawingChildren) { child->mDrawingParent = newParent; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 996d686371..15f4330e27 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -287,7 +287,7 @@ public: bool setOverrideScalingMode(int32_t overrideScalingMode); void setInfo(uint32_t type, uint32_t appId); bool reparentChildren(const sp& layer); - void reparentChildrenForDrawing(const sp& layer); + void setChildrenDrawingParent(const sp& layer); bool reparent(const sp& newParentHandle); bool detachChildren(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 11658e8b49..ba611c6b26 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4460,9 +4460,9 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, ReparentForDrawing(const sp& oldParent, const sp& newParent) : oldParent(oldParent), newParent(newParent) { - oldParent->reparentChildrenForDrawing(newParent); + oldParent->setChildrenDrawingParent(newParent); } - ~ReparentForDrawing() { newParent->reparentChildrenForDrawing(oldParent); } + ~ReparentForDrawing() { oldParent->setChildrenDrawingParent(oldParent); } }; void render(std::function drawLayers) override { diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index fd219913df..4e9db72268 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2384,6 +2384,17 @@ TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) { verify(); } +TEST_F(ScreenCaptureChildOnlyTest, RegressionTest76099859) { + SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true); + + // Even though the parent is hidden we should still capture the child. + verify(); + + // Verify everything was properly hidden when rendering the full-screen. + screenshot()->expectBGColor(0,0); +} + + TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { auto fgHandle = mFGSurfaceControl->getHandle(); -- cgit v1.2.3-59-g8ed1b From 7794ec15e59fd6dd389ba05379ff81287c6ab52f Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 14 Mar 2018 13:28:39 -0700 Subject: Use unique_ptr for proto parser to handle destruction. There's a memory leak where Layers created for the proto tree are not removed when no longer used. This ensures that there's a unique_ptr for each parser layer created so it will be automatically destroyed when out of scope. Merged-In: I56731d28a39e7d9d157c59065102d97f316f3b7d Change-Id: I56731d28a39e7d9d157c59065102d97f316f3b7d Fixes: 74071380 Test: adb shell dumpsys SurfaceFlinger Test: LayerProtoStress.mem_info no longer shows increased memory --- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- .../surfaceflinger/layerproto/LayerProtoParser.cpp | 66 +++++++++++----------- .../include/layerproto/LayerProtoParser.h | 11 ++-- services/surfaceflinger/tests/Android.bp | 1 + services/surfaceflinger/tests/Stress_test.cpp | 64 ++++++++++++++++++++- 5 files changed, 105 insertions(+), 39 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 11658e8b49..1d7a98f1fb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3980,7 +3980,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); auto layerTree = LayerProtoParser::generateLayerTree(layersProto); - result.append(LayerProtoParser::layersToString(layerTree).c_str()); + result.append(LayerProtoParser::layersToString(std::move(layerTree)).c_str()); /* * Dump Display state diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index bf37e1e156..c9b7fe55b8 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include #include #include @@ -24,7 +23,7 @@ using android::base::StringPrintf; namespace android { namespace surfaceflinger { -bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) { +bool sortLayers(LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) { uint32_t ls = lhs->layerStack; uint32_t rs = rhs->layerStack; if (ls != rs) return ls < rs; @@ -38,20 +37,25 @@ bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Laye return lhs->id < rhs->id; } -std::vector LayerProtoParser::generateLayerTree( +bool sortLayerUniquePtrs(const std::unique_ptr& lhs, + const std::unique_ptr& rhs) { + return sortLayers(lhs.get(), rhs.get()); +} + +std::vector> LayerProtoParser::generateLayerTree( const LayersProto& layersProto) { - auto layerMap = generateMap(layersProto); - - std::vector layers; - std::for_each(layerMap.begin(), layerMap.end(), - [&](const std::pair& ref) { - if (ref.second->parent == nullptr) { - // only save top level layers - layers.push_back(ref.second); - } - }); - - std::sort(layers.begin(), layers.end(), sortLayers); + std::unordered_map layerMap = generateMap(layersProto); + std::vector> layers; + + for (std::pair kv : layerMap) { + if (kv.second->parent == nullptr) { + // Make unique_ptr for top level layers since they are not children. This ensures there + // will only be one unique_ptr made for each layer. + layers.push_back(std::unique_ptr(kv.second)); + } + } + + std::sort(layers.begin(), layers.end(), sortLayerUniquePtrs); return layers; } @@ -155,63 +159,61 @@ void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto, for (int i = 0; i < layerProto.children_size(); i++) { if (layerMap.count(layerProto.children(i)) > 0) { - auto childLayer = layerMap[layerProto.children(i)]; - currLayer->children.push_back(childLayer); + // Only make unique_ptrs for children since they are guaranteed to be unique, only one + // parent per child. This ensures there will only be one unique_ptr made for each layer. + currLayer->children.push_back(std::unique_ptr(layerMap[layerProto.children(i)])); } } for (int i = 0; i < layerProto.relatives_size(); i++) { if (layerMap.count(layerProto.relatives(i)) > 0) { - auto relativeLayer = layerMap[layerProto.relatives(i)]; - currLayer->relatives.push_back(relativeLayer); + currLayer->relatives.push_back(layerMap[layerProto.relatives(i)]); } } if (layerProto.has_parent()) { if (layerMap.count(layerProto.parent()) > 0) { - auto parentLayer = layerMap[layerProto.parent()]; - currLayer->parent = parentLayer; + currLayer->parent = layerMap[layerProto.parent()]; } } if (layerProto.has_z_order_relative_of()) { if (layerMap.count(layerProto.z_order_relative_of()) > 0) { - auto relativeLayer = layerMap[layerProto.z_order_relative_of()]; - currLayer->zOrderRelativeOf = relativeLayer; + currLayer->zOrderRelativeOf = layerMap[layerProto.z_order_relative_of()]; } } } std::string LayerProtoParser::layersToString( - const std::vector layers) { + std::vector> layers) { std::string result; - for (const LayerProtoParser::Layer* layer : layers) { + for (std::unique_ptr& layer : layers) { if (layer->zOrderRelativeOf != nullptr) { continue; } - result.append(layerToString(layer).c_str()); + result.append(layerToString(layer.get()).c_str()); } return result; } -std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer) { +std::string LayerProtoParser::layerToString(LayerProtoParser::Layer* layer) { std::string result; - std::vector traverse(layer->relatives); - for (const LayerProtoParser::Layer* child : layer->children) { + std::vector traverse(layer->relatives); + for (std::unique_ptr& child : layer->children) { if (child->zOrderRelativeOf != nullptr) { continue; } - traverse.push_back(child); + traverse.push_back(child.get()); } std::sort(traverse.begin(), traverse.end(), sortLayers); size_t i = 0; for (; i < traverse.size(); i++) { - const auto& relative = traverse[i]; + auto& relative = traverse[i]; if (relative->z >= 0) { break; } @@ -220,7 +222,7 @@ std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer result.append(layer->to_string().c_str()); result.append("\n"); for (; i < traverse.size(); i++) { - const auto& relative = traverse[i]; + auto& relative = traverse[i]; result.append(layerToString(relative).c_str()); } diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 78c6cd1345..b81a9595d2 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -18,6 +18,7 @@ #include +#include #include #include @@ -68,8 +69,8 @@ public: public: int32_t id; std::string name; - std::vector children; - std::vector relatives; + std::vector> children; + std::vector relatives; std::string type; LayerProtoParser::Region transparentRegion; LayerProtoParser::Region visibleRegion; @@ -99,8 +100,8 @@ public: std::string to_string() const; }; - static std::vector generateLayerTree(const LayersProto& layersProto); - static std::string layersToString(const std::vector layers); + static std::vector> generateLayerTree(const LayersProto& layersProto); + static std::string layersToString(std::vector> layers); private: static std::unordered_map generateMap(const LayersProto& layersProto); @@ -113,7 +114,7 @@ private: static void updateChildrenAndRelative(const LayerProto& layerProto, std::unordered_map& layerMap); - static std::string layerToString(const LayerProtoParser::Layer* layer); + static std::string layerToString(LayerProtoParser::Layer* layer); }; } // namespace surfaceflinger diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index 7d3da329ce..7523399dbf 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -33,6 +33,7 @@ cc_test { "libEGL", "libGLESv2", "libgui", + "liblayers_proto", "liblog", "libprotobuf-cpp-full", "libui", diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp index 33dd2f55d3..4577153df2 100644 --- a/services/surfaceflinger/tests/Stress_test.cpp +++ b/services/surfaceflinger/tests/Stress_test.cpp @@ -22,7 +22,7 @@ #include #include - +#include namespace android { @@ -47,4 +47,66 @@ TEST(SurfaceFlingerStress, create_and_destroy) { } } +surfaceflinger::LayersProto generateLayerProto() { + surfaceflinger::LayersProto layersProto; + std::array layers = {}; + for (size_t i = 0; i < layers.size(); ++i) { + layers[i] = layersProto.add_layers(); + layers[i]->set_id(i); + } + + layers[0]->add_children(1); + layers[1]->set_parent(0); + layers[0]->add_children(2); + layers[2]->set_parent(0); + layers[0]->add_children(3); + layers[3]->set_parent(0); + layers[2]->add_children(4); + layers[4]->set_parent(2); + layers[3]->add_children(5); + layers[5]->set_parent(3); + layers[5]->add_children(6); + layers[6]->set_parent(5); + layers[5]->add_children(7); + layers[7]->set_parent(5); + layers[6]->add_children(8); + layers[8]->set_parent(6); + + layers[4]->set_z_order_relative_of(3); + layers[3]->add_relatives(4); + layers[8]->set_z_order_relative_of(9); + layers[9]->add_relatives(8); + layers[3]->set_z_order_relative_of(1); + layers[1]->add_relatives(3); + +/* ---------------------------- + * - 0 - - 9 - + * / | \ + * 1 2 3(1) + * | | + * 4(3) 5 + * / \ + * 6 7 + * | + * 8(9) + * -------------------------- */ + + return layersProto; +} + +TEST(LayerProtoStress, mem_info) { + std::string cmd = "dumpsys meminfo "; + cmd += std::to_string(getpid()); + system(cmd.c_str()); + for (int i = 0; i < 100000; i++) { + surfaceflinger::LayersProto layersProto = generateLayerProto(); + auto layerTree = surfaceflinger::LayerProtoParser::generateLayerTree(layersProto); + // Allow some layerTrees to just fall out of scope (instead of std::move) + if (i % 2) { + surfaceflinger::LayerProtoParser::layersToString(std::move(layerTree)); + } + } + system(cmd.c_str()); +} + } -- cgit v1.2.3-59-g8ed1b From ccd348460ca25890a8fb709e82e6f780e3ce878e Mon Sep 17 00:00:00 2001 From: rongliu Date: Wed, 14 Mar 2018 12:26:23 -0700 Subject: Pass correct window type and app id to hw composer. 1. Set -1 as default value for window type and app id. 2. When send layer information to hal, layers inherit type and app id from parent node when parent node has valid type/appId. 3. Add window type and app id to SurfaceFlinger dumpsys. Bug: 74622357 Test: Manual test. Several things verified: 1. Android settings layer, status bar layer, nav bar layer have valid window type and appId when start android settings. 2. Layers without buffer have window type -1 and app id -1. 3. When send layers to hal, Chrome SurfaceView layer inherit type and app id from its parent (MainActivity layer). Change-Id: I8d6ad274ca18b61d1bbf6b28f7def5160b55b1e7 Merged-In: I8d6ad274ca18b61d1bbf6b28f7def5160b55b1e7 --- libs/gui/ISurfaceComposerClient.cpp | 4 ++-- libs/gui/SurfaceComposerClient.cpp | 8 ++++---- libs/gui/include/gui/ISurfaceComposerClient.h | 4 ++-- libs/gui/include/gui/SurfaceComposerClient.h | 8 ++++---- services/surfaceflinger/Client.cpp | 8 ++++---- services/surfaceflinger/Client.h | 2 +- services/surfaceflinger/Layer.cpp | 10 +++++++--- services/surfaceflinger/Layer.h | 6 +++--- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.h | 2 +- services/surfaceflinger/layerproto/LayerProtoParser.cpp | 5 ++++- .../layerproto/include/layerproto/LayerProtoParser.h | 2 ++ services/surfaceflinger/layerproto/layers.proto | 2 ++ 13 files changed, 37 insertions(+), 26 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 679f44b57b..a6890eeb19 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -47,8 +47,8 @@ public: ~BpSurfaceComposerClient() override; status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format, - uint32_t flags, const sp& parent, uint32_t windowType, - uint32_t ownerUid, sp* handle, + uint32_t flags, const sp& parent, int32_t windowType, + int32_t ownerUid, sp* handle, sp* gbp) override { return callRemote(Tag::CREATE_SURFACE, name, width, height, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 38f0eb7422..3cf49d6723 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -609,8 +609,8 @@ sp SurfaceComposerClient::createSurface( PixelFormat format, uint32_t flags, SurfaceControl* parent, - uint32_t windowType, - uint32_t ownerUid) + int32_t windowType, + int32_t ownerUid) { sp s; createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid); @@ -625,8 +625,8 @@ status_t SurfaceComposerClient::createSurfaceChecked( sp* outSurface, uint32_t flags, SurfaceControl* parent, - uint32_t windowType, - uint32_t ownerUid) + int32_t windowType, + int32_t ownerUid) { sp sur; status_t err = NO_ERROR; diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index d5bbef25f8..8dfc99a4b7 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -49,8 +49,8 @@ public: * Requires ACCESS_SURFACE_FLINGER permission */ virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags, const sp& parent, uint32_t windowType, - uint32_t ownerUid, sp* handle, + uint32_t flags, const sp& parent, int32_t windowType, + int32_t ownerUid, sp* handle, sp* gbp) = 0; /* diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 5ce20adb89..b45ce4f86c 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -111,8 +111,8 @@ public: PixelFormat format, // pixel-format desired uint32_t flags = 0, // usage flags SurfaceControl* parent = nullptr, // parent - uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - uint32_t ownerUid = 0 // UID of the task + int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) + int32_t ownerUid = -1 // UID of the task ); status_t createSurfaceChecked( @@ -123,8 +123,8 @@ public: sp* outSurface, uint32_t flags = 0, // usage flags SurfaceControl* parent = nullptr, // parent - uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - uint32_t ownerUid = 0 // UID of the task + int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) + int32_t ownerUid = -1 // UID of the task ); //! Create a virtual display diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 0c9f0e21e1..c90024b863 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -143,7 +143,7 @@ status_t Client::onTransact( status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - const sp& parentHandle, uint32_t windowType, uint32_t ownerUid, + const sp& parentHandle, int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp) { @@ -180,13 +180,13 @@ status_t Client::createSurface( PixelFormat format; uint32_t flags; sp* parent; - uint32_t windowType; - uint32_t ownerUid; + int32_t windowType; + int32_t ownerUid; public: MessageCreateLayer(SurfaceFlinger* flinger, const String8& name, Client* client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - sp* handle, uint32_t windowType, uint32_t ownerUid, + sp* handle, int32_t windowType, int32_t ownerUid, sp* gbp, sp* parent) : flinger(flinger), client(client), diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 2aab28f37d..c7df9f780f 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -58,7 +58,7 @@ private: virtual status_t createSurface( const String8& name, uint32_t w, uint32_t h,PixelFormat format, uint32_t flags, - const sp& parent, uint32_t windowType, uint32_t ownerUid, + const sp& parent, int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 44e60edb37..6bd187f820 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -587,8 +587,10 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z sp parent = mDrawingParent.promote(); if (parent.get()) { auto& parentState = parent->getDrawingState(); - type = parentState.type; - appId = parentState.appId; + if (parentState.type >= 0 || parentState.appId >= 0) { + type = parentState.type; + appId = parentState.appId; + } } error = hwcLayer->setInfo(type, appId); @@ -1313,7 +1315,7 @@ bool Layer::setOverrideScalingMode(int32_t scalingMode) { return true; } -void Layer::setInfo(uint32_t type, uint32_t appId) { +void Layer::setInfo(int32_t type, int32_t appId) { mCurrentState.appId = appId; mCurrentState.type = type; mCurrentState.modified = true; @@ -1919,6 +1921,8 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_queued_frames(getQueuedFrameCount()); layerInfo->set_refresh_pending(isBufferLatched()); + layerInfo->set_window_type(state.type); + layerInfo->set_app_id(state.appId); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 996d686371..f2fa5b9321 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -203,8 +203,8 @@ public: Region requestedTransparentRegion; android_dataspace dataSpace; - uint32_t appId; - uint32_t type; + int32_t appId; + int32_t type; // If non-null, a Surface this Surface's Z-order is interpreted relative to. wp zOrderRelativeOf; @@ -285,7 +285,7 @@ public: void deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber); void deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber); bool setOverrideScalingMode(int32_t overrideScalingMode); - void setInfo(uint32_t type, uint32_t appId); + void setInfo(int32_t type, int32_t appId); bool reparentChildren(const sp& layer); void reparentChildrenForDrawing(const sp& layer); bool reparent(const sp& newParentHandle); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a6e0a9ec98..472e45f16f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3318,7 +3318,7 @@ status_t SurfaceFlinger::createLayer( const String8& name, const sp& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - uint32_t windowType, uint32_t ownerUid, sp* handle, + int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp, sp* parent) { if (int32_t(w|h) < 0) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 51001e599d..333dcbcd17 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -485,7 +485,7 @@ private: */ status_t createLayer(const String8& name, const sp& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - uint32_t windowType, uint32_t ownerUid, sp* handle, + int32_t windowType, int32_t ownerUid, sp* handle, sp* gbp, sp* parent); status_t createBufferLayer(const sp& client, const String8& name, diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index c9b7fe55b8..47e5d1ff0b 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -106,6 +106,8 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer()); layer->queuedFrames = layerProto.queued_frames(); layer->refreshPending = layerProto.refresh_pending(); + layer->windowType = layerProto.window_type(); + layer->appId = layerProto.app_id(); return layer; } @@ -281,7 +283,8 @@ std::string LayerProtoParser::Layer::to_string() const { StringAppendF(&result, " zOrderRelativeOf=%s\n", zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str()); StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str()); - StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames, refreshPending); + StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending); + StringAppendF(&result, " windowType=%d, appId=%d", windowType, appId); return result; } diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index b81a9595d2..b56a6fbb97 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -96,6 +96,8 @@ public: LayerProtoParser::ActiveBuffer activeBuffer; int32_t queuedFrames; bool refreshPending; + int32_t windowType; + int32_t appId; std::string to_string() const; }; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index d27dc9b2ea..f18386b1ac 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -64,6 +64,8 @@ message LayerProto { // The number of frames available. optional int32 queued_frames = 28; optional bool refresh_pending = 29; + optional int32 window_type = 30; + optional int32 app_id = 31; } message PositionProto { -- cgit v1.2.3-59-g8ed1b From 2d3ee6dda3547b08b0de3373da5b6b2edb223fa9 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 17 Jan 2018 13:42:24 -0800 Subject: SF: libsurfaceflinger_unittest should skip SF ctor This reduces the cost of constructing a SurfaceFlinger instance for each test, but it means the tests must take care to set up all internal state that is needed for each test. [Test execution time reduced from 6.1 to 3.1ms] Test: libsurfaceflinger_unittest passes on Pixel XL Bug: 74827900 Change-Id: I7eed4fd274cae521fe0f22b655cf3343cee66342 (cherry picked from commit ac648ee7ead13b4c23fb0d12e00b7f15f844f04f) --- services/surfaceflinger/SurfaceFlinger.cpp | 6 ++++-- services/surfaceflinger/SurfaceFlinger.h | 3 +++ services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a6e0a9ec98..0352731914 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -163,7 +163,7 @@ SurfaceFlingerBE::SurfaceFlingerBE() mComposerSequenceId(0) { } -SurfaceFlinger::SurfaceFlinger() +SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag) : BnSurfaceComposer(), mTransactionFlags(0), mTransactionPending(false), @@ -195,7 +195,9 @@ SurfaceFlinger::SurfaceFlinger() mNumLayers(0), mVrFlingerRequestsDisplay(false), mMainThreadId(std::this_thread::get_id()), - mCreateBufferQueue(&BufferQueue::createBufferQueue) { + mCreateBufferQueue(&BufferQueue::createBufferQueue) {} + +SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { ALOGI("SurfaceFlinger is starting"); vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 51001e599d..b2261b0c4a 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -265,6 +265,9 @@ public: return "SurfaceFlinger"; } + struct SkipInitializationTag {}; + static constexpr SkipInitializationTag SkipInitialization; + explicit SurfaceFlinger(SkipInitializationTag) ANDROID_API; SurfaceFlinger() ANDROID_API; // must be called before clients can connect diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 067b09ad02..3e58eb8813 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -98,7 +98,7 @@ public: auto& mutableConfigs() { return this->mConfigs; } }; - sp mFlinger = new SurfaceFlinger(); + sp mFlinger = new SurfaceFlinger(SurfaceFlinger::SkipInitialization); }; } // namespace android -- cgit v1.2.3-59-g8ed1b From 9123ae5f9da83f1d0efd2260c5ecd84f66a11fb7 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Mon, 22 Jan 2018 17:14:00 -0800 Subject: SF: Separate MessageQueue into interface and impl Test: Builds Bug: 74827900 Change-Id: I906892c00b6cb9adca3fbdd72a03001c2d72cbfc (cherry picked from commit 3fcdef18f41330b4f1e3f1e2b9a33c544e8803b0) --- services/surfaceflinger/MessageQueue.cpp | 16 ++++++---- services/surfaceflinger/MessageQueue.h | 49 +++++++++++++++++++----------- services/surfaceflinger/SurfaceFlinger.cpp | 21 +++++++------ services/surfaceflinger/SurfaceFlinger.h | 2 +- 4 files changed, 54 insertions(+), 34 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp index 5a6ff4dd98..056d381eb9 100644 --- a/services/surfaceflinger/MessageQueue.cpp +++ b/services/surfaceflinger/MessageQueue.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include "EventThread.h" @@ -45,6 +46,12 @@ void MessageBase::handleMessage(const Message&) { // --------------------------------------------------------------------------- +MessageQueue::~MessageQueue() = default; + +// --------------------------------------------------------------------------- + +namespace impl { + void MessageQueue::Handler::dispatchRefresh() { if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) { mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH)); @@ -72,17 +79,13 @@ void MessageQueue::Handler::handleMessage(const Message& message) { // --------------------------------------------------------------------------- -MessageQueue::MessageQueue() {} - -MessageQueue::~MessageQueue() {} - void MessageQueue::init(const sp& flinger) { mFlinger = flinger; mLooper = new Looper(true); mHandler = new Handler(*this); } -void MessageQueue::setEventThread(EventThread* eventThread) { +void MessageQueue::setEventThread(android::EventThread* eventThread) { if (mEventThread == eventThread) { return; } @@ -159,4 +162,5 @@ int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) { // --------------------------------------------------------------------------- -}; // namespace android +} // namespace impl +} // namespace android diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h index dcfc716524..90d1c72450 100644 --- a/services/surfaceflinger/MessageQueue.h +++ b/services/surfaceflinger/MessageQueue.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include "Barrier.h" @@ -34,7 +34,6 @@ namespace android { -class IDisplayEventConnection; class EventThread; class SurfaceFlinger; @@ -77,6 +76,27 @@ private: // --------------------------------------------------------------------------- class MessageQueue { +public: + enum { + INVALIDATE = 0, + REFRESH = 1, + }; + + virtual ~MessageQueue(); + + virtual void init(const sp& flinger) = 0; + virtual void setEventThread(EventThread* events) = 0; + virtual void waitMessage() = 0; + virtual status_t postMessage(const sp& message, nsecs_t reltime = 0) = 0; + virtual void invalidate() = 0; + virtual void refresh() = 0; +}; + +// --------------------------------------------------------------------------- + +namespace impl { + +class MessageQueue final : public android::MessageQueue { class Handler : public MessageHandler { enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 }; MessageQueue& mQueue; @@ -93,7 +113,7 @@ class MessageQueue { sp mFlinger; sp mLooper; - EventThread* mEventThread; + android::EventThread* mEventThread; sp mEvents; gui::BitTube mEventTube; sp mHandler; @@ -102,27 +122,22 @@ class MessageQueue { int eventReceiver(int fd, int events); public: - enum { - INVALIDATE = 0, - REFRESH = 1, - }; - - MessageQueue(); - ~MessageQueue(); - void init(const sp& flinger); - void setEventThread(EventThread* events); + ~MessageQueue() override = default; + void init(const sp& flinger) override; + void setEventThread(android::EventThread* events) override; - void waitMessage(); - status_t postMessage(const sp& message, nsecs_t reltime = 0); + void waitMessage() override; + status_t postMessage(const sp& message, nsecs_t reltime = 0) override; // sends INVALIDATE message at next VSYNC - void invalidate(); + void invalidate() override; // sends REFRESH message at next VSYNC - void refresh(); + void refresh() override; }; // --------------------------------------------------------------------------- -}; // namespace android +} // namespace impl +} // namespace android #endif /* ANDROID_MESSAGE_QUEUE_H */ diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0352731914..e5a15d58af 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -284,7 +284,7 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { void SurfaceFlinger::onFirstRef() { - mEventQueue.init(this); + mEventQueue->init(this); } SurfaceFlinger::~SurfaceFlinger() @@ -590,9 +590,10 @@ void SurfaceFlinger::init() { mSfEventThreadSource = std::make_unique(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf"); + mSFEventThread = std::make_unique(mSfEventThreadSource.get(), *this, true, "sfEventThread"); - mEventQueue.setEventThread(mSFEventThread.get()); + mEventQueue->setEventThread(mSFEventThread.get()); // Get a RenderEngine for the given display / config (can't fail) getBE().mRenderEngine = @@ -1081,10 +1082,10 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) { std::make_unique(mVSyncInjector.get(), *this, false, "injEventThread"); } - mEventQueue.setEventThread(mInjectorEventThread.get()); + mEventQueue->setEventThread(mInjectorEventThread.get()); } else { ALOGV("VSync Injections disabled"); - mEventQueue.setEventThread(mSFEventThread.get()); + mEventQueue->setEventThread(mSFEventThread.get()); } mInjectVSyncs = enable; @@ -1149,30 +1150,30 @@ sp SurfaceFlinger::createDisplayEventConnection( // ---------------------------------------------------------------------------- void SurfaceFlinger::waitForEvent() { - mEventQueue.waitMessage(); + mEventQueue->waitMessage(); } void SurfaceFlinger::signalTransaction() { - mEventQueue.invalidate(); + mEventQueue->invalidate(); } void SurfaceFlinger::signalLayerUpdate() { - mEventQueue.invalidate(); + mEventQueue->invalidate(); } void SurfaceFlinger::signalRefresh() { mRefreshPending = true; - mEventQueue.refresh(); + mEventQueue->refresh(); } status_t SurfaceFlinger::postMessageAsync(const sp& msg, nsecs_t reltime, uint32_t /* flags */) { - return mEventQueue.postMessage(msg, reltime); + return mEventQueue->postMessage(msg, reltime); } status_t SurfaceFlinger::postMessageSync(const sp& msg, nsecs_t reltime, uint32_t /* flags */) { - status_t res = mEventQueue.postMessage(msg, reltime); + status_t res = mEventQueue->postMessage(msg, reltime); if (res == NO_ERROR) { msg->wait(); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b2261b0c4a..989e20d6fe 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -785,7 +785,7 @@ private: bool mLayerTripleBufferingDisabled = false; // these are thread safe - mutable MessageQueue mEventQueue; + mutable std::unique_ptr mEventQueue{std::make_unique()}; FrameTracker mAnimFrameTracker; DispSync mPrimaryDispSync; -- cgit v1.2.3-59-g8ed1b From 4d2348551e73b4990aedc83db17a336b533316e6 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Mon, 22 Jan 2018 17:21:36 -0800 Subject: SF: Separate SurfaceInterceptor into interface and impl SurfaceInterceptor is now an abstract interface. impl::SurfaceInterceptor is the normal implementation. This allows unit tests to replace it with a GMock. Test: Builds Bug: 74827900 Change-Id: I4d5bb2649b0c7a8ec1e6c0abf01ab53174d06a19 (cherry picked from commit 4dccc413ddf822ca6f1856fd2d8ab80185203eed) --- services/surfaceflinger/BufferLayer.cpp | 6 +-- services/surfaceflinger/EventThread.cpp | 2 +- services/surfaceflinger/Layer.h | 6 ++- services/surfaceflinger/SurfaceFlinger.cpp | 25 +++++---- services/surfaceflinger/SurfaceFlinger.h | 3 +- services/surfaceflinger/SurfaceInterceptor.cpp | 6 ++- services/surfaceflinger/SurfaceInterceptor.h | 72 ++++++++++++++++++++------ 7 files changed, 85 insertions(+), 35 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index d22c021139..9200207f4a 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -690,9 +690,9 @@ void BufferLayer::onFrameAvailable(const BufferItem& item) { // Add this buffer from our internal queue tracker { // Autolock scope Mutex::Autolock lock(mQueueItemLock); - mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), - item.mGraphicBuffer->getHeight(), - item.mFrameNumber); + mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), + item.mGraphicBuffer->getHeight(), + item.mFrameNumber); // Reset the frame number tracker when we receive the first buffer after // a frame number reset if (item.mFrameNumber == 1) { diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index 1f4f5a53f4..bb9c0703ed 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -217,7 +217,7 @@ Vector > EventThread::waitForEventLocked( if (timestamp) { // we have a vsync event to dispatch if (mInterceptVSyncs) { - mFlinger.mInterceptor.saveVSyncEvent(timestamp); + mFlinger.mInterceptor->saveVSyncEvent(timestamp); } *event = mVSyncEvent[i]; mVSyncEvent[i].header.timestamp = 0; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 996d686371..3d572c67fb 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -66,6 +66,10 @@ class SurfaceFlinger; class LayerDebugInfo; class LayerBE; +namespace impl { +class SurfaceInterceptor; +} + // --------------------------------------------------------------------------- struct CompositionInfo { @@ -593,7 +597,7 @@ protected: virtual void onFirstRef(); - friend class SurfaceInterceptor; + friend class impl::SurfaceInterceptor; void commitTransaction(const State& stateToCommit); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e5a15d58af..932b92e653 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -186,7 +186,6 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag) mLastTransactionTime(0), mBootFinished(false), mForceFullDamage(false), - mInterceptor(this), mPrimaryDispSync("PrimaryDispSync"), mPrimaryHWVsyncEnabled(false), mHWVsyncAvailable(false), @@ -350,7 +349,7 @@ sp SurfaceFlinger::createDisplay(const String8& displayName, DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure); info.displayName = displayName; mCurrentState.displays.add(token, info); - mInterceptor.saveDisplayCreation(info); + mInterceptor->saveDisplayCreation(info); return token; } @@ -368,7 +367,7 @@ void SurfaceFlinger::destroyDisplay(const sp& display) { ALOGE("destroyDisplay called for non-virtual display"); return; } - mInterceptor.saveDisplayDeletion(info.displayId); + mInterceptor->saveDisplayDeletion(info.displayId); mCurrentState.displays.removeItemsAt(idx); setTransactionFlags(eDisplayTransactionNeeded); } @@ -2131,7 +2130,7 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ? "Built-in Screen" : "External Screen"; mCurrentState.displays.add(mBuiltinDisplays[displayType], info); - mInterceptor.saveDisplayCreation(info); + mInterceptor->saveDisplayCreation(info); } } else { ALOGV("Removing built in display %d", displayType); @@ -2139,7 +2138,7 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { ssize_t idx = mCurrentState.displays.indexOfKey(mBuiltinDisplays[displayType]); if (idx >= 0) { const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx)); - mInterceptor.saveDisplayDeletion(info.displayId); + mInterceptor->saveDisplayDeletion(info.displayId); mCurrentState.displays.removeItemsAt(idx); } mBuiltinDisplays[displayType].clear(); @@ -3066,8 +3065,8 @@ void SurfaceFlinger::setTransactionState( } if (transactionFlags) { - if (mInterceptor.isEnabled()) { - mInterceptor.saveTransaction(states, mCurrentState.displays, displays, flags); + if (mInterceptor->isEnabled()) { + mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags); } // this triggers the transaction @@ -3370,7 +3369,7 @@ status_t SurfaceFlinger::createLayer( if (result != NO_ERROR) { return result; } - mInterceptor.saveSurfaceCreation(layer); + mInterceptor->saveSurfaceCreation(layer); setTransactionFlags(eTransactionNeeded); return result; @@ -3442,7 +3441,7 @@ status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp l(client->getLayerUser(handle)); if (l != nullptr) { - mInterceptor.saveSurfaceDeletion(l); + mInterceptor->saveSurfaceDeletion(l); err = removeLayer(l); ALOGE_IF(err<0 && err != NAME_NOT_FOUND, "error removing layer=%p (%s)", l.get(), strerror(-err)); @@ -3524,14 +3523,14 @@ void SurfaceFlinger::setPowerModeInternal(const sp& hw, return; } - if (mInterceptor.isEnabled()) { + if (mInterceptor->isEnabled()) { ConditionalLock lock(mStateLock, !stateLockHeld); ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken()); if (idx < 0) { ALOGW("Surface Interceptor SavePowerMode: invalid display token"); return; } - mInterceptor.savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode); + mInterceptor->savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode); } if (currentMode == HWC_POWER_MODE_OFF) { @@ -4335,11 +4334,11 @@ status_t SurfaceFlinger::onTransact( n = data.readInt32(); if (n) { ALOGV("Interceptor enabled"); - mInterceptor.enable(mDrawingState.layersSortedByZ, mDrawingState.displays); + mInterceptor->enable(mDrawingState.layersSortedByZ, mDrawingState.displays); } else{ ALOGV("Interceptor disabled"); - mInterceptor.disable(); + mInterceptor->disable(); } return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 989e20d6fe..7d15622d4f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -777,7 +777,8 @@ private: bool mBootFinished; bool mForceFullDamage; bool mPropagateBackpressure = true; - SurfaceInterceptor mInterceptor; + std::unique_ptr mInterceptor = + std::make_unique(this); SurfaceTracing mTracing; bool mUseHwcVirtualDisplays = false; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index eeb492978c..4596a21f12 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -31,6 +31,10 @@ namespace android { // ---------------------------------------------------------------------------- +SurfaceInterceptor::~SurfaceInterceptor() = default; + +namespace impl { + SurfaceInterceptor::SurfaceInterceptor(SurfaceFlinger* flinger) : mFlinger(flinger) { @@ -593,5 +597,5 @@ void SurfaceInterceptor::savePowerModeUpdate(int32_t displayId, int32_t mode) { addPowerModeUpdateLocked(createTraceIncrementLocked(), displayId, mode); } - +} // namespace impl } // namespace android diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 30ebcc6a1c..96defcc265 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -21,48 +21,89 @@ #include +#include + +#include #include +#include #include +#include "DisplayDevice.h" + namespace android { class BufferItem; class Layer; class SurfaceFlinger; +struct ComposerState; +struct DisplayDeviceState; struct DisplayState; struct layer_state_t; constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat"; +class SurfaceInterceptor { +public: + virtual ~SurfaceInterceptor(); + + // Both vectors are used to capture the current state of SF as the initial snapshot in the trace + virtual void enable(const SortedVector>& layers, + const DefaultKeyedVector, DisplayDeviceState>& displays) = 0; + virtual void disable() = 0; + virtual bool isEnabled() = 0; + + // Intercept display and surface transactions + virtual void saveTransaction( + const Vector& stateUpdates, + const DefaultKeyedVector, DisplayDeviceState>& displays, + const Vector& changedDisplays, uint32_t flags) = 0; + + // Intercept surface data + virtual void saveSurfaceCreation(const sp& layer) = 0; + virtual void saveSurfaceDeletion(const sp& layer) = 0; + virtual void saveBufferUpdate(const sp& layer, uint32_t width, uint32_t height, + uint64_t frameNumber) = 0; + + // Intercept display data + virtual void saveDisplayCreation(const DisplayDeviceState& info) = 0; + virtual void saveDisplayDeletion(int32_t displayId) = 0; + virtual void savePowerModeUpdate(int32_t displayId, int32_t mode) = 0; + virtual void saveVSyncEvent(nsecs_t timestamp) = 0; +}; + +namespace impl { + /* * SurfaceInterceptor intercepts and stores incoming streams of window * properties on SurfaceFlinger. */ -class SurfaceInterceptor { +class SurfaceInterceptor final : public android::SurfaceInterceptor { public: - SurfaceInterceptor(SurfaceFlinger* const flinger); + explicit SurfaceInterceptor(SurfaceFlinger* const flinger); + ~SurfaceInterceptor() override = default; + // Both vectors are used to capture the current state of SF as the initial snapshot in the trace void enable(const SortedVector>& layers, - const DefaultKeyedVector< wp, DisplayDeviceState>& displays); - void disable(); - bool isEnabled(); + const DefaultKeyedVector, DisplayDeviceState>& displays) override; + void disable() override; + bool isEnabled() override; // Intercept display and surface transactions void saveTransaction(const Vector& stateUpdates, - const DefaultKeyedVector< wp, DisplayDeviceState>& displays, - const Vector& changedDisplays, uint32_t flags); + const DefaultKeyedVector, DisplayDeviceState>& displays, + const Vector& changedDisplays, uint32_t flags) override; // Intercept surface data - void saveSurfaceCreation(const sp& layer); - void saveSurfaceDeletion(const sp& layer); + void saveSurfaceCreation(const sp& layer) override; + void saveSurfaceDeletion(const sp& layer) override; void saveBufferUpdate(const sp& layer, uint32_t width, uint32_t height, - uint64_t frameNumber); + uint64_t frameNumber) override; // Intercept display data - void saveDisplayCreation(const DisplayDeviceState& info); - void saveDisplayDeletion(int32_t displayId); - void savePowerModeUpdate(int32_t displayId, int32_t mode); - void saveVSyncEvent(nsecs_t timestamp); + void saveDisplayCreation(const DisplayDeviceState& info) override; + void saveDisplayDeletion(int32_t displayId) override; + void savePowerModeUpdate(int32_t displayId, int32_t mode) override; + void saveVSyncEvent(nsecs_t timestamp) override; private: // The creation increments of Surfaces and Displays do not contain enough information to capture @@ -134,6 +175,7 @@ private: SurfaceFlinger* const mFlinger; }; -} +} // namespace impl +} // namespace android #endif // ANDROID_SURFACEINTERCEPTOR_H -- cgit v1.2.3-59-g8ed1b From 0c3a88319136a8ce0e7050ef5695610a986ce900 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Mon, 22 Jan 2018 17:31:47 -0800 Subject: SF: Separate EventControlThread into interface and impl Test: Builds Bug: 74827900 Change-Id: Ib79503860bf9409cc71d98e2e845ffaff114fbb1 (cherry picked from commit 379adc10ebe94eec8c7754d262c6184fbfb3f0a3) --- services/surfaceflinger/EventControlThread.cpp | 5 +++++ services/surfaceflinger/EventControlThread.h | 15 +++++++++++++-- services/surfaceflinger/SurfaceFlinger.cpp | 5 ++--- 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp index ac54059360..fb6cff5705 100644 --- a/services/surfaceflinger/EventControlThread.cpp +++ b/services/surfaceflinger/EventControlThread.cpp @@ -26,6 +26,10 @@ namespace android { +EventControlThread::~EventControlThread() = default; + +namespace impl { + EventControlThread::EventControlThread(EventControlThread::SetVSyncEnabledFunction function) : mSetVSyncEnabled(function) { pthread_setname_np(mThread.native_handle(), "EventControlThread"); @@ -67,4 +71,5 @@ void EventControlThread::threadMain() NO_THREAD_SAFETY_ANALYSIS { } } +} // namespace impl } // namespace android diff --git a/services/surfaceflinger/EventControlThread.h b/services/surfaceflinger/EventControlThread.h index 321fb79831..9be4e7cd8e 100644 --- a/services/surfaceflinger/EventControlThread.h +++ b/services/surfaceflinger/EventControlThread.h @@ -16,8 +16,8 @@ #pragma once -#include #include +#include #include #include #include @@ -29,13 +29,23 @@ namespace android { class SurfaceFlinger; class EventControlThread { +public: + virtual ~EventControlThread(); + + virtual void setVsyncEnabled(bool enabled) = 0; +}; + +namespace impl { + +class EventControlThread final : public android::EventControlThread { public: using SetVSyncEnabledFunction = std::function; explicit EventControlThread(SetVSyncEnabledFunction function); ~EventControlThread(); - void setVsyncEnabled(bool enabled); + // EventControlThread implementation + void setVsyncEnabled(bool enabled) override; private: void threadMain(); @@ -51,4 +61,5 @@ private: std::thread mThread{&EventControlThread::threadMain, this}; }; +} // namespace impl } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 932b92e653..cdf126e9e2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -639,9 +639,8 @@ void SurfaceFlinger::init() { } } - mEventControlThread = std::make_unique([this](bool enabled) { - setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); - }); + mEventControlThread = std::make_unique( + [this](bool enabled) { setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); }); // initialize our drawing state mDrawingState = mCurrentState; -- cgit v1.2.3-59-g8ed1b From 0959483fe3a2e4f70c91d4a0579ddbe03c9d3262 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Mon, 22 Jan 2018 17:48:03 -0800 Subject: SF: Refactor display device creation Move display device creation to its own function which handles all initialization before creating a DisplayDevice instance, which now just simply constructs an instance from the passed values. Also introduces a factory to abstract creating libgui Surface instances, so that can be replaced by the test. Test: Builds Bug: 74827900 Change-Id: Ia80c865dc96b300033c506cc3093e563bcab787b (cherry picked from commit 99d3da56143c24c99ba73b830c9e16a6f9814770) --- services/surfaceflinger/DisplayDevice.cpp | 70 ++++--------- services/surfaceflinger/DisplayDevice.h | 9 +- services/surfaceflinger/SurfaceFlinger.cpp | 155 ++++++++++++++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 21 ++++ 4 files changed, 157 insertions(+), 98 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 92d5e21f34..fe0b30ba35 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -57,9 +57,6 @@ using namespace android; using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; -static bool useTripleFramebuffer = getInt64< ISurfaceFlingerConfigs, - &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2) >= 3; - /* * Initialize the display to the specified values. * @@ -74,72 +71,43 @@ DisplayDevice::DisplayDevice( int32_t hwcId, bool isSecure, const wp& displayToken, + const sp& nativeWindow, const sp& displaySurface, - const sp& producer, + std::unique_ptr renderSurface, + int displayWidth, + int displayHeight, bool supportWideColor, - bool supportHdr) + bool supportHdr, + int initialPowerMode) : lastCompositionHadVisibleLayers(false), mFlinger(flinger), mType(type), mHwcDisplayId(hwcId), mDisplayToken(displayToken), + mNativeWindow(nativeWindow), mDisplaySurface(displaySurface), - mSurface{flinger->getRenderEngine().createSurface()}, - mDisplayWidth(), - mDisplayHeight(), - mPageFlipCount(), + mSurface{std::move(renderSurface)}, + mDisplayWidth(displayWidth), + mDisplayHeight(displayHeight), + mPageFlipCount(0), mIsSecure(isSecure), mLayerStack(NO_LAYER_STACK), mOrientation(), - mPowerMode(HWC_POWER_MODE_OFF), - mActiveConfig(0) + mViewport(Rect::INVALID_RECT), + mFrame(Rect::INVALID_RECT), + mPowerMode(initialPowerMode), + mActiveConfig(0), + mActiveColorMode(ColorMode::NATIVE), + mDisplayHasWideColor(supportWideColor), + mDisplayHasHdr(supportHdr) { // clang-format on - Surface* surface; - mNativeWindow = surface = new Surface(producer, false); - ANativeWindow* const window = mNativeWindow.get(); - - mActiveColorMode = ColorMode::NATIVE; - mDisplayHasWideColor = supportWideColor; - mDisplayHasHdr = supportHdr; - - /* - * Create our display's surface - */ - mSurface->setCritical(mType == DisplayDevice::DISPLAY_PRIMARY); - mSurface->setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL); - mSurface->setNativeWindow(window); - mDisplayWidth = mSurface->queryWidth(); - mDisplayHeight = mSurface->queryHeight(); - - // Make sure that composition can never be stalled by a virtual display - // consumer that isn't processing buffers fast enough. We have to do this - // in two places: - // * Here, in case the display is composed entirely by HWC. - // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the - // window's swap interval in eglMakeCurrent, so they'll override the - // interval we set here. - if (mType >= DisplayDevice::DISPLAY_VIRTUAL) - window->setSwapInterval(window, 0); - - mPageFlipCount = 0; - mViewport.makeInvalid(); - mFrame.makeInvalid(); - - // virtual displays are always considered enabled - mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ? - HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; // initialize the display orientation transform. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); - - if (useTripleFramebuffer) { - surface->allocateBuffers(); - } } -DisplayDevice::~DisplayDevice() { -} +DisplayDevice::~DisplayDevice() = default; void DisplayDevice::disconnect(HWComposer& hwc) { if (mHwcDisplayId >= 0) { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 737971f83d..fbb0d462f3 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -77,9 +77,14 @@ public: int32_t hwcId, bool isSecure, const wp& displayToken, + const sp& nativeWindow, const sp& displaySurface, - const sp& producer, - bool supportWideColor, bool supportHdr); + std::unique_ptr renderSurface, + int displayWidth, + int displayHeight, + bool supportWideColor, + bool supportHdr, + int initialPowerMode); // clang-format on ~DisplayDevice(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cdf126e9e2..b99e17f16f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -154,6 +154,32 @@ bool useTrebleTestingOverride() { return std::string(value) == "true"; } +NativeWindowSurface::~NativeWindowSurface() = default; + +namespace impl { + +class NativeWindowSurface final : public android::NativeWindowSurface { +public: + static std::unique_ptr create( + const sp& producer) { + return std::make_unique(producer); + } + + explicit NativeWindowSurface(const sp& producer) + : surface(new Surface(producer, false)) {} + + ~NativeWindowSurface() override = default; + +private: + sp getNativeWindow() const override { return surface; } + + void preallocateBuffers() override { surface->allocateBuffers(); } + + sp surface; +}; + +} // namespace impl + SurfaceFlingerBE::SurfaceFlingerBE() : mHwcServiceName(getHwcServiceName()), mRenderEngine(nullptr), @@ -194,7 +220,8 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag) mNumLayers(0), mVrFlingerRequestsDisplay(false), mMainThreadId(std::this_thread::get_id()), - mCreateBufferQueue(&BufferQueue::createBufferQueue) {} + mCreateBufferQueue(&BufferQueue::createBufferQueue), + mCreateNativeWindowSurface(&impl::NativeWindowSurface::create) {} SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { ALOGI("SurfaceFlinger is starting"); @@ -2080,7 +2107,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) } DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display, - HWC2::Connection connection) const { + HWC2::Connection connection) const { // Figure out whether the event is for the primary display or an // external display by matching the Hwc display id against one for a // connected display. If we did not find a match, we then check what @@ -2149,6 +2176,84 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { mPendingHotplugEvents.clear(); } +sp SurfaceFlinger::setupNewDisplayDeviceInternal( + const wp& display, int hwcId, const DisplayDeviceState& state, + const sp& dispSurface, const sp& producer) { + bool hasWideColorSupport = false; + if (hasWideColorDisplay) { + std::vector modes = getHwComposer().getColorModes(state.type); + for (ColorMode colorMode : modes) { + switch (colorMode) { + case ColorMode::DISPLAY_P3: + case ColorMode::ADOBE_RGB: + case ColorMode::DCI_P3: + hasWideColorSupport = true; + break; + default: + break; + } + } + } + + bool hasHdrSupport = false; + std::unique_ptr hdrCapabilities = + getHwComposer().getHdrCapabilities(state.type); + if (hdrCapabilities) { + const std::vector types = hdrCapabilities->getSupportedHdrTypes(); + auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10); + hasHdrSupport = iter != types.cend(); + } + + auto nativeWindowSurface = mCreateNativeWindowSurface(producer); + auto nativeWindow = nativeWindowSurface->getNativeWindow(); + + /* + * Create our display's surface + */ + std::unique_ptr renderSurface = getRenderEngine().createSurface(); + renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY); + renderSurface->setAsync(state.type >= DisplayDevice::DISPLAY_VIRTUAL); + renderSurface->setNativeWindow(nativeWindow.get()); + const int displayWidth = renderSurface->queryWidth(); + const int displayHeight = renderSurface->queryHeight(); + + // Make sure that composition can never be stalled by a virtual display + // consumer that isn't processing buffers fast enough. We have to do this + // in two places: + // * Here, in case the display is composed entirely by HWC. + // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the + // window's swap interval in eglMakeCurrent, so they'll override the + // interval we set here. + if (state.type >= DisplayDevice::DISPLAY_VIRTUAL) { + nativeWindow->setSwapInterval(nativeWindow.get(), 0); + } + + // virtual displays are always considered enabled + auto initialPowerMode = (state.type >= DisplayDevice::DISPLAY_VIRTUAL) ? HWC_POWER_MODE_NORMAL + : HWC_POWER_MODE_OFF; + + sp hw = + new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow, + dispSurface, std::move(renderSurface), displayWidth, displayHeight, + hasWideColorSupport, hasHdrSupport, initialPowerMode); + + if (maxFrameBufferAcquiredBuffers >= 3) { + nativeWindowSurface->preallocateBuffers(); + } + + ColorMode defaultColorMode = ColorMode::NATIVE; + if (hasWideColorSupport) { + defaultColorMode = ColorMode::SRGB; + } + setActiveColorModeInternal(hw, defaultColorMode); + hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN); + hw->setLayerStack(state.layerStack); + hw->setProjection(state.orientation, state.viewport, state.frame); + hw->setDisplayName(state.displayName); + + return hw; +} + void SurfaceFlinger::processDisplayChangesLocked() { // here we take advantage of Vector's copy-on-write semantics to // improve performance by skipping the transaction entirely when @@ -2271,50 +2376,10 @@ void SurfaceFlinger::processDisplayChangesLocked() { } const wp& display(curr.keyAt(i)); - if (dispSurface != nullptr) { - bool hasWideColorSupport = false; - if (hasWideColorDisplay) { - std::vector modes = - getHwComposer().getColorModes(state.type); - for (ColorMode colorMode : modes) { - switch (colorMode) { - case ColorMode::DISPLAY_P3: - case ColorMode::ADOBE_RGB: - case ColorMode::DCI_P3: - hasWideColorSupport = true; - break; - default: - break; - } - } - } - - bool hasHdrSupport = false; - std::unique_ptr hdrCapabilities = - getHwComposer().getHdrCapabilities(state.type); - if (hdrCapabilities) { - const std::vector types = hdrCapabilities->getSupportedHdrTypes(); - auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10); - hasHdrSupport = iter != types.cend(); - } - - sp hw = - new DisplayDevice(this, state.type, hwcId, state.isSecure, display, - dispSurface, producer, hasWideColorSupport, - hasHdrSupport); - - ColorMode defaultColorMode = ColorMode::NATIVE; - if (hasWideColorSupport) { - defaultColorMode = ColorMode::SRGB; - } - setActiveColorModeInternal(hw, defaultColorMode); - hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN); - hw->setLayerStack(state.layerStack); - hw->setProjection(state.orientation, state.viewport, state.frame); - hw->setDisplayName(state.displayName); - - mDisplays.add(display, hw); + mDisplays.add(display, + setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface, + producer)); if (!state.isVirtualDisplay()) { mEventThread->onHotplugReceived(state.type, true); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 7d15622d4f..ec9633d057 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -118,6 +118,19 @@ enum { eTransactionMask = 0x07 }; +// A thin interface to abstract creating instances of Surface (gui/Surface.h) to +// use as a NativeWindow. +class NativeWindowSurface { +public: + virtual ~NativeWindowSurface(); + + // Gets the NativeWindow to use for the surface. + virtual sp getNativeWindow() const = 0; + + // Indicates that the surface should allocate its buffers now. + virtual void preallocateBuffers() = 0; +}; + class SurfaceFlingerBE { public: @@ -646,6 +659,10 @@ private: */ DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display, HWC2::Connection connection) const; + sp setupNewDisplayDeviceInternal(const wp& display, int hwcId, + const DisplayDeviceState& state, + const sp& dispSurface, + const sp& producer); void processDisplayChangesLocked(); void processDisplayHotplugEventsLocked(); @@ -837,6 +854,10 @@ private: bool /* consumerIsSurfaceFlinger */)>; CreateBufferQueueFunction mCreateBufferQueue; + using CreateNativeWindowSurfaceFunction = + std::function(const sp&)>; + CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface; + SurfaceFlingerBE mBE; }; }; // namespace android -- cgit v1.2.3-59-g8ed1b From 05ee4c93fb050fc17b61396ab9ec17bfd7e122b4 Mon Sep 17 00:00:00 2001 From: Alice Sheng Date: Tue, 27 Mar 2018 15:03:10 -0700 Subject: Add log for when a display mode change finishes. Adds logging when surfaceflinger finishes changing display mode at the end of setPowerMode, which is useful to measure wakeup latency. Bug: 77151769 Change-Id: I0930c4ea1f5e7872a2e3d47031da7933fe1ab5de --- services/surfaceflinger/SurfaceFlinger.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 11658e8b49..dd9486800b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3590,6 +3590,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp& hw, ALOGE("Attempting to set unknown power mode: %d\n", mode); getHwComposer().setPowerMode(type, mode); } + ALOGD("Finished set power mode=%d, type=%d", mode, hw->getDisplayType()); } void SurfaceFlinger::setPowerMode(const sp& display, int mode) { -- cgit v1.2.3-59-g8ed1b From 1e04361db1b65d3998edbf820078ccfaed477cb6 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 1 Mar 2018 09:45:09 -0800 Subject: surfaceflinger: minor dumpsys improvements In the order of importance, - fix eglGetConfigAttrib calls - mark Zs as relative in minidump - dump DisplayDevice wide color states - rename pixelformat to defaultPixelFormat in layer state - better grouping and indentation for DisplayDevice dump Bug: 76415976 Test: dumpsys Change-Id: If9254ffe43cb1de82d562fcc27e828d54eba9387 --- services/surfaceflinger/DisplayDevice.cpp | 6 +++++- services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp | 4 ++-- services/surfaceflinger/Layer.cpp | 6 +++++- services/surfaceflinger/RenderEngine/Surface.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 2 ++ services/surfaceflinger/layerproto/LayerProtoParser.cpp | 2 +- 6 files changed, 16 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 92d5e21f34..09d7855134 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -486,7 +486,11 @@ void DisplayDevice::dump(String8& result) const { tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]); auto const surface = static_cast(window); android_dataspace dataspace = surface->getBuffersDataSpace(); - result.appendFormat(" dataspace: %s (%d)\n", dataspaceDetails(dataspace).c_str(), dataspace); + result.appendFormat(" wideColor=%d, hdr=%d, colorMode=%s, dataspace: %s (%d)\n", + mDisplayHasWideColor, mDisplayHasHdr, + decodeColorMode(mActiveColorMode).c_str(), + dataspaceDetails(dataspace).c_str(), dataspace); + String8 surfaceDump; mDisplaySurface->dumpAsString(surfaceDump); diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 4faba3b77a..9398bdec92 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -177,9 +177,9 @@ void FramebufferSurface::onFrameCommitted() { void FramebufferSurface::dumpAsString(String8& result) const { Mutex::Autolock lock(mMutex); - result.appendFormat("FramebufferSurface: dataspace: %s(%d)\n", + result.appendFormat(" FramebufferSurface: dataspace: %s(%d)\n", dataspaceDetails(mDataSpace).c_str(), mDataSpace); - ConsumerBase::dumpLocked(result, ""); + ConsumerBase::dumpLocked(result, " "); } void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 44e60edb37..806df1ba21 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1492,7 +1492,11 @@ void Layer::miniDump(String8& result, int32_t hwcId) const { const Layer::State& layerState(getDrawingState()); const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId); - result.appendFormat(" %10d | ", layerState.z); + if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) { + result.appendFormat(" rel %6d | ", layerState.z); + } else { + result.appendFormat(" %10d | ", layerState.z); + } result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str()); const Rect& frame = hwcInfo.displayFrame; result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp index 3c29e4b2ea..0d20f1fd87 100644 --- a/services/surfaceflinger/RenderEngine/Surface.cpp +++ b/services/surfaceflinger/RenderEngine/Surface.cpp @@ -66,7 +66,7 @@ void Surface::swapBuffers() const { EGLint Surface::queryConfig(EGLint attrib) const { EGLint value; - if (!eglGetConfigAttrib(mEGLConfig, mEGLConfig, attrib, &value)) { + if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) { value = 0; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a6e0a9ec98..e5c220e58c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3981,6 +3981,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); auto layerTree = LayerProtoParser::generateLayerTree(layersProto); result.append(LayerProtoParser::layersToString(std::move(layerTree)).c_str()); + result.append("\n"); /* * Dump Display state @@ -3993,6 +3994,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, const sp& hw(mDisplays[dpy]); hw->dump(result); } + result.append("\n"); /* * Dump SurfaceFlinger global state diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index c9b7fe55b8..e1df1c093e 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -271,7 +271,7 @@ std::string LayerProtoParser::Layer::to_string() const { finalCrop.to_string().c_str()); StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate); StringAppendF(&result, "dataspace=%s, ", dataspace.c_str()); - StringAppendF(&result, "pixelformat=%s, ", pixelFormat.c_str()); + StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str()); StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ", static_cast(color.r), static_cast(color.g), static_cast(color.b), static_cast(color.a), flags); -- cgit v1.2.3-59-g8ed1b From d432a7c40dfa6c5498038ec652db54478df966c1 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Fri, 23 Mar 2018 16:05:31 -0700 Subject: SF: Clean up updateTransformHint() processing. While working on ag/3368935, an unintentional duplicate call was added to Layer::updateTransform() from SurfaceFlinger::handleTransactionLocked(). This patch removes the duplicate call. In examining the code, the update conditions also did not appear to be set correctly. They have been adjusted so that a display change or a significant layer change (such as a layer being added) will result in an update. Bug: 76223411 Test: No immediate issues observed on a Pixel XL. Change-Id: I59220837b22ae1f76d7d9d376c1ebd24d8d14105 --- services/surfaceflinger/SurfaceFlinger.cpp | 24 ++++++++++++------------ services/surfaceflinger/SurfaceFlinger.h | 3 ++- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f2cbc897b9..7201f19632 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2357,7 +2357,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) processDisplayHotplugEventsLocked(); } - if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) { + if (transactionFlags & (eDisplayLayerStackChanged|eDisplayTransactionNeeded)) { // The transform hint might have changed for some layers // (either because a display has changed, or because a layer // as changed). @@ -2404,18 +2404,18 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } } - if (transactionFlags & eDisplayTransactionNeeded) { - if (disp == nullptr) { - // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to - // redraw after transform hint changes. See bug 8508397. + if (disp == nullptr) { + // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to + // redraw after transform hint changes. See bug 8508397. - // could be null when this layer is using a layerStack - // that is not visible on any display. Also can occur at - // screen off/on times. - disp = getDefaultDisplayDeviceLocked(); - } - layer->updateTransformHint(disp); + // could be null when this layer is using a layerStack + // that is not visible on any display. Also can occur at + // screen off/on times. + disp = getDefaultDisplayDeviceLocked(); } + + // disp can be null if there is no display available at all to get + // the transform hint from. if (disp != nullptr) { layer->updateTransformHint(disp); } @@ -3250,7 +3250,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState mCurrentState.layersSortedByZ.add(layer); // we need traversal (state changed) // AND transaction (list changed) - flags |= eTransactionNeeded|eTraversalNeeded; + flags |= eTransactionNeeded|eTraversalNeeded|eDisplayLayerStackChanged; } } if (what & layer_state_t::eDeferTransaction) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 333dcbcd17..432205096f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -115,7 +115,8 @@ enum { eTransactionNeeded = 0x01, eTraversalNeeded = 0x02, eDisplayTransactionNeeded = 0x04, - eTransactionMask = 0x07 + eDisplayLayerStackChanged = 0x08, + eTransactionMask = 0x0f, }; class SurfaceFlingerBE -- cgit v1.2.3-59-g8ed1b From fd997e0969100418b4df8b8d97d21d497afa76c3 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 28 Mar 2018 15:29:00 -0700 Subject: Add proper namespace to GraphicTypes. Renamed GraphicsTypes.h to GraphicTypes.h and added proper namespace to avoid naming conflict. BUG: 77156734 Test: Build and flash Change-Id: Ibd9f454b5b72d5f8c6d94a3869a60a1bf821f106 Merged-In: Ibd9f454b5b72d5f8c6d94a3869a60a1bf821f106 --- libs/gui/ISurfaceComposer.cpp | 2 ++ libs/gui/Surface.cpp | 2 ++ libs/gui/SurfaceComposerClient.cpp | 2 ++ libs/gui/include/gui/ISurfaceComposer.h | 8 +++--- libs/gui/include/gui/SurfaceComposerClient.h | 9 ++++--- libs/gui/tests/Surface_test.cpp | 1 + libs/ui/DebugUtils.cpp | 2 +- libs/ui/include/ui/DebugUtils.h | 4 +-- libs/ui/include/ui/GraphicTypes.h | 30 ++++++++++++++++++++++ libs/ui/include/ui/GraphicsTypes.h | 26 ------------------- services/surfaceflinger/DisplayDevice.cpp | 7 ++--- services/surfaceflinger/DisplayDevice.h | 10 ++++---- services/surfaceflinger/DisplayHardware/HWC2.cpp | 18 +++---------- services/surfaceflinger/DisplayHardware/HWC2.h | 11 ++++---- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 8 +++--- .../surfaceflinger/DisplayHardware/HWComposer.h | 6 ++--- services/surfaceflinger/RenderArea.h | 4 +-- services/surfaceflinger/SurfaceFlinger.cpp | 1 + services/surfaceflinger/SurfaceFlinger.h | 10 ++++---- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 4 +-- 20 files changed, 85 insertions(+), 80 deletions(-) create mode 100644 libs/ui/include/ui/GraphicTypes.h delete mode 100644 libs/ui/include/ui/GraphicsTypes.h (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 0244bb512e..e22bc708c9 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -43,6 +43,8 @@ namespace android { +using ui::ColorMode; + class BpSurfaceComposer : public BpInterface { public: diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 2e1c24b755..6a1aebd6d6 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -44,6 +44,8 @@ namespace android { +using ui::ColorMode; + Surface::Surface(const sp& bufferProducer, bool controlledByApp) : mGraphicBufferProducer(bufferProducer), mCrop(Rect::EMPTY_RECT), diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 4c041bc4f5..bbf681ea90 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -43,6 +43,8 @@ #include namespace android { + +using ui::ColorMode; // --------------------------------------------------------------------------- ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index afe9358c0a..3591090172 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include @@ -161,10 +161,10 @@ public: virtual status_t setActiveConfig(const sp& display, int id) = 0; virtual status_t getDisplayColorModes(const sp& display, - Vector* outColorModes) = 0; - virtual ColorMode getActiveColorMode(const sp& display) = 0; + Vector* outColorModes) = 0; + virtual ui::ColorMode getActiveColorMode(const sp& display) = 0; virtual status_t setActiveColorMode(const sp& display, - ColorMode colorMode) = 0; + ui::ColorMode colorMode) = 0; /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index b45ce4f86c..ffc22f6437 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -89,13 +89,14 @@ public: // Gets the list of supported color modes for the given display static status_t getDisplayColorModes(const sp& display, - Vector* outColorModes); + Vector* outColorModes); // Gets the active color mode for the given display - static ColorMode getActiveColorMode(const sp& display); + static ui::ColorMode getActiveColorMode(const sp& display); // Sets the active color mode for the given display - static status_t setActiveColorMode(const sp& display, ColorMode colorMode); + static status_t setActiveColorMode(const sp& display, + ui::ColorMode colorMode); /* Triggers screen on/off or low power mode and waits for it to complete */ static void setDisplayPowerMode(const sp& display, int mode); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index df391ed4bb..2c02ba657d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -42,6 +42,7 @@ using namespace std::chrono_literals; // retrieve wide-color and hdr settings from configstore using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +using ui::ColorMode; using Transaction = SurfaceComposerClient::Transaction; diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp index d7e191db89..d7d8618703 100644 --- a/libs/ui/DebugUtils.cpp +++ b/libs/ui/DebugUtils.cpp @@ -22,7 +22,7 @@ #include using android::base::StringPrintf; -using android::ColorMode; +using android::ui::ColorMode; std::string decodeStandard(android_dataspace dataspace) { const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK); diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h index 33701070a9..6350d0cf95 100644 --- a/libs/ui/include/ui/DebugUtils.h +++ b/libs/ui/include/ui/DebugUtils.h @@ -16,7 +16,7 @@ #pragma once -#include +#include #include #include @@ -29,6 +29,6 @@ std::string decodeStandard(android_dataspace dataspace); std::string decodeTransfer(android_dataspace dataspace); std::string decodeRange(android_dataspace dataspace); std::string dataspaceDetails(android_dataspace dataspace); -std::string decodeColorMode(android::ColorMode colormode); +std::string decodeColorMode(android::ui::ColorMode colormode); std::string decodePixelFormat(android::PixelFormat format); std::string to_string(const android::Rect& rect); diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h new file mode 100644 index 0000000000..39893b268a --- /dev/null +++ b/libs/ui/include/ui/GraphicTypes.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +// android::ui::* in this header file will alias different types as +// the HIDL interface is updated. +namespace android { +namespace ui { + +using android::hardware::graphics::common::V1_0::ColorMode; + +} // namespace ui +} // namespace android diff --git a/libs/ui/include/ui/GraphicsTypes.h b/libs/ui/include/ui/GraphicsTypes.h deleted file mode 100644 index fa9a812d97..0000000000 --- a/libs/ui/include/ui/GraphicsTypes.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -namespace android { - -using android::hardware::graphics::common::V1_0::ColorMode; - -} // namespace android diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index fe0b30ba35..bab6a71057 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -49,13 +49,12 @@ #include #include -// ---------------------------------------------------------------------------- -using namespace android; -// ---------------------------------------------------------------------------- +namespace android { // retrieve triple buffer setting from configstore using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +using android::ui::ColorMode; /* * Initialize the display to the specified values. @@ -474,3 +473,5 @@ DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type, bool isS viewport.makeInvalid(); frame.makeInvalid(); } + +} // namespace android diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index fbb0d462f3..df729f5ce9 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -31,7 +31,7 @@ #include #include -#include +#include #include "RenderArea.h" #include "RenderEngine/Surface.h" @@ -161,8 +161,8 @@ public: void setPowerMode(int mode); bool isDisplayOn() const; - ColorMode getActiveColorMode() const; - void setActiveColorMode(ColorMode mode); + ui::ColorMode getActiveColorMode() const; + void setActiveColorMode(ui::ColorMode mode); void setCompositionDataSpace(android_dataspace dataspace); /* ------------------------------------------------------------------------ @@ -236,7 +236,7 @@ private: // Current active config int mActiveConfig; // current active color mode - ColorMode mActiveColorMode; + ui::ColorMode mActiveColorMode; // Need to know if display is wide-color capable or not. // Initialized by SurfaceFlinger when the DisplayDevice is created. @@ -285,7 +285,7 @@ public: bool needsFiltering() const override { return mDevice->needsFiltering(); } Rect getSourceCrop() const override { return mSourceCrop; } bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); } - ColorMode getActiveColorMode() const override { + ui::ColorMode getActiveColorMode() const override { return mDevice->getActiveColorMode(); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 0c77aba498..98daec3e47 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -362,20 +362,10 @@ Error Display::getChangedCompositionTypes( return Error::None; } -Error Display::getColorModes(std::vector* outModes) const +Error Display::getColorModes(std::vector* outModes) const { - std::vector modes; - auto intError = mComposer.getColorModes(mId, &modes); - uint32_t numModes = modes.size(); - auto error = static_cast(intError); - if (error != Error::None) { - return error; - } - - outModes->resize(numModes); - for (size_t i = 0; i < numModes; i++) { - (*outModes)[i] = modes[i]; - } + auto intError = mComposer.getColorModes(mId, outModes); + return static_cast(intError); return Error::None; } @@ -537,7 +527,7 @@ Error Display::setClientTarget(uint32_t slot, const sp& target, return static_cast(intError); } -Error Display::setColorMode(android::ColorMode mode) +Error Display::setColorMode(android::ui::ColorMode mode) { auto intError = mComposer.setColorMode(mId, mode); return static_cast(intError); diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 5b53b54d71..71c094a035 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -211,7 +211,7 @@ public: [[clang::warn_unused_result]] Error getChangedCompositionTypes( std::unordered_map* outTypes); [[clang::warn_unused_result]] Error getColorModes( - std::vector* outModes) const; + std::vector* outModes) const; // Doesn't call into the HWC2 device, so no errors are possible std::vector> getConfigs() const; @@ -235,7 +235,8 @@ public: uint32_t slot, const android::sp& target, const android::sp& acquireFence, android_dataspace_t dataspace); - [[clang::warn_unused_result]] Error setColorMode(android::ColorMode mode); + [[clang::warn_unused_result]] Error setColorMode( + android::ui::ColorMode mode); [[clang::warn_unused_result]] Error setColorTransform( const android::mat4& matrix, android_color_transform_t hint); [[clang::warn_unused_result]] Error setOutputBuffer( @@ -246,8 +247,8 @@ public: [[clang::warn_unused_result]] Error validate(uint32_t* outNumTypes, uint32_t* outNumRequests); [[clang::warn_unused_result]] Error presentOrValidate(uint32_t* outNumTypes, - uint32_t* outNumRequests, - android::sp* outPresentFence, uint32_t* state); + uint32_t* outNumRequests, + android::sp* outPresentFence, uint32_t* state); // Other Display methods diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 6d5917db2f..6bf2ee9362 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -311,8 +311,8 @@ std::shared_ptr return config; } -std::vector HWComposer::getColorModes(int32_t displayId) const { - std::vector modes; +std::vector HWComposer::getColorModes(int32_t displayId) const { + std::vector modes; if (!isValidDisplay(displayId)) { ALOGE("getColorModes: Attempted to access invalid display %d", @@ -324,13 +324,13 @@ std::vector HWComposer::getColorModes(int32_t displayId) const { if (error != HWC2::Error::None) { ALOGE("getColorModes failed for display %d: %s (%d)", displayId, to_string(error).c_str(), static_cast(error)); - return std::vector(); + return std::vector(); } return modes; } -status_t HWComposer::setActiveColorMode(int32_t displayId, ColorMode mode) { +status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode) { if (!isValidDisplay(displayId)) { ALOGE("setActiveColorMode: Display %d is not valid", displayId); return BAD_INDEX; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index c442b2f191..0366a0d164 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include @@ -159,9 +159,9 @@ public: std::shared_ptr getActiveConfig(int32_t displayId) const; - std::vector getColorModes(int32_t displayId) const; + std::vector getColorModes(int32_t displayId) const; - status_t setActiveColorMode(int32_t displayId, ColorMode mode); + status_t setActiveColorMode(int32_t displayId, ui::ColorMode mode); bool isUsingVrComposer() const; diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index b9c4909d5a..bf0707f13b 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "Transform.h" @@ -32,7 +32,7 @@ public: int getReqWidth() const { return mReqWidth; }; Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; virtual bool getWideColorSupport() const = 0; - virtual ColorMode getActiveColorMode() const = 0; + virtual ui::ColorMode getActiveColorMode() const = 0; status_t updateDimensions(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5c69b98b98..09e67b62cb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -104,6 +104,7 @@ namespace android { using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +using ui::ColorMode; namespace { class ConditionalLock { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 42d8112b90..448509bc8f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -410,9 +410,9 @@ private: Vector* configs); virtual int getActiveConfig(const sp& display); virtual status_t getDisplayColorModes(const sp& display, - Vector* configs); - virtual ColorMode getActiveColorMode(const sp& display); - virtual status_t setActiveColorMode(const sp& display, ColorMode colorMode); + Vector* configs); + virtual ui::ColorMode getActiveColorMode(const sp& display); + virtual status_t setActiveColorMode(const sp& display, ui::ColorMode colorMode); virtual void setPowerMode(const sp& display, int mode); virtual status_t setActiveConfig(const sp& display, int id); virtual status_t clearAnimationFrameStats(); @@ -462,7 +462,7 @@ private: bool stateLockHeld); // Called on the main thread in response to setActiveColorMode() - void setActiveColorModeInternal(const sp& hw, ColorMode colorMode); + void setActiveColorModeInternal(const sp& hw, ui::ColorMode colorMode); // Returns whether the transaction actually modified any state bool handleMessageTransaction(); @@ -635,7 +635,7 @@ private: // Given a dataSpace, returns the appropriate color_mode to use // to display that dataSpace. - ColorMode pickColorMode(android_dataspace dataSpace) const; + ui::ColorMode pickColorMode(android_dataspace dataSpace) const; android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b, bool hasHdr) const; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 86e2e1ec30..b3f1b69f71 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #define HWC2_INCLUDE_STRINGIFICATION #define HWC2_USE_CPP11 @@ -35,7 +35,7 @@ #include "Hwc2TestClientTarget.h" #include "Hwc2TestVirtualDisplay.h" -using android::ColorMode; +using android::ui::ColorMode; void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); -- cgit v1.2.3-59-g8ed1b From 068e31b929b40a1bc9be742c04cbdf5b04f3ce97 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 21 Feb 2018 13:02:45 -0800 Subject: Implement Display Layer Stats Try to collect data for analyzing how many display controller layers we need and what we use them for. Also part of a bug fixing for potential memory leak of existing layer tracing work of winscope. Test: adb shell dumpsys SurfaceFlinger --enable-layer-stats Test: adb shell dumpsys SurfaceFlinger --disable-layer-stats Test: adb shell dumpsys SurfaceFlinger --clear-layer-stats Test: adb shell dumpsys SurfaceFlinger --dump-layer-stats Bug: b/73668062 Change-Id: Ie08aa85d34db2c2c767b8e27eb5aad6f7c3fb975 Merged-In: Ie08aa85d34db2c2c767b8e27eb5aad6f7c3fb975 --- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/Layer.cpp | 16 ++ services/surfaceflinger/Layer.h | 6 +- services/surfaceflinger/LayerProtoHelper.cpp | 7 + services/surfaceflinger/LayerProtoHelper.h | 3 +- services/surfaceflinger/LayerStats.cpp | 181 +++++++++++++++++++++ services/surfaceflinger/LayerStats.h | 69 ++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 67 ++++++++ services/surfaceflinger/SurfaceFlinger.h | 4 + .../surfaceflinger/layerproto/LayerProtoParser.cpp | 22 +++ .../include/layerproto/LayerProtoParser.h | 21 +++ services/surfaceflinger/layerproto/layers.proto | 20 ++- 12 files changed, 412 insertions(+), 5 deletions(-) create mode 100644 services/surfaceflinger/LayerStats.cpp create mode 100644 services/surfaceflinger/LayerStats.h (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index ba28eb5298..ff994f515c 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -105,6 +105,7 @@ filegroup { "Layer.cpp", "LayerProtoHelper.cpp", "LayerRejecter.cpp", + "LayerStats.cpp", "LayerVector.cpp", "MessageQueue.cpp", "MonitoredProducer.cpp", diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 166ac22fa2..c3eb1bc85f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -635,6 +635,7 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z hwcInfo.forceClientComposition = true; } else { auto transform = static_cast(orientation); + hwcInfo.transform = transform; auto error = hwcLayer->setTransform(transform); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set transform %s: " @@ -1923,6 +1924,21 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_app_id(state.appId); } +void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) { + writeToProto(layerInfo, LayerVector::StateSet::Drawing); + + const auto& hwcInfo = getBE().mHwcLayers.at(hwcId); + + const Rect& frame = hwcInfo.displayFrame; + LayerProtoHelper::writeToProto(frame, layerInfo->mutable_hwc_frame()); + + const FloatRect& crop = hwcInfo.sourceCrop; + LayerProtoHelper::writeToProto(crop, layerInfo->mutable_hwc_crop()); + + const int32_t transform = static_cast(hwcInfo.transform); + layerInfo->set_hwc_transform(transform); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9a9b5e60c8..69ffb2018c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -113,7 +113,8 @@ public: layer(nullptr), forceClientComposition(false), compositionType(HWC2::Composition::Invalid), - clearClientTarget(false) {} + clearClientTarget(false), + transform(HWC2::Transform::None) {} HWComposer* hwc; HWC2::Layer* layer; @@ -123,6 +124,7 @@ public: Rect displayFrame; FloatRect sourceCrop; HWComposerBufferCache bufferCache; + HWC2::Transform transform; }; // A layer can be attached to multiple displays when operating in mirror mode @@ -357,6 +359,8 @@ public: void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); + void writeToProto(LayerProto* layerInfo, int32_t hwcId); + protected: /* * onDraw - draws the surface. diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 6a33148d27..cc3955087a 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -37,6 +37,13 @@ void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) { rectProto->set_right(rect.right); } +void LayerProtoHelper::writeToProto(const FloatRect& rect, FloatRectProto* rectProto) { + rectProto->set_left(rect.left); + rectProto->set_top(rect.top); + rectProto->set_bottom(rect.bottom); + rectProto->set_right(rect.right); +} + void LayerProtoHelper::writeToProto(const half4 color, ColorProto* colorProto) { colorProto->set_r(color.r); colorProto->set_g(color.g); diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 45a0b5d173..860da63ed2 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -29,6 +29,7 @@ namespace surfaceflinger { class LayerProtoHelper { public: static void writeToProto(const Rect& rect, RectProto* rectProto); + static void writeToProto(const FloatRect& rect, FloatRectProto* rectProto); static void writeToProto(const Region& region, RegionProto* regionProto); static void writeToProto(const half4 color, ColorProto* colorProto); static void writeToProto(const Transform& transform, TransformProto* transformProto); @@ -36,4 +37,4 @@ public: }; } // namespace surfaceflinger -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp new file mode 100644 index 0000000000..dc99b41cc6 --- /dev/null +++ b/services/surfaceflinger/LayerStats.cpp @@ -0,0 +1,181 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#undef LOG_TAG +#define LOG_TAG "LayerStats" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "LayerStats.h" +#include "DisplayHardware/HWComposer.h" + +#include +#include +#include +#include + +namespace android { + +void LayerStats::enable() { + ATRACE_CALL(); + std::lock_guard lock(mMutex); + if (mEnabled) return; + mLayerStatsMap.clear(); + mEnabled = true; + ALOGD("Logging enabled"); +} + +void LayerStats::disable() { + ATRACE_CALL(); + std::lock_guard lock(mMutex); + if (!mEnabled) return; + mEnabled = false; + ALOGD("Logging disabled"); +} + +void LayerStats::clear() { + ATRACE_CALL(); + std::lock_guard lock(mMutex); + mLayerStatsMap.clear(); + ALOGD("Cleared current layer stats"); +} + +bool LayerStats::isEnabled() { + return mEnabled; +} + +void LayerStats::traverseLayerTreeStatsLocked( + std::vector> layerTree, + const LayerProtoParser::LayerGlobal* layerGlobal) { + for (std::unique_ptr& layer : layerTree) { + if (!layer) continue; + traverseLayerTreeStatsLocked(std::move(layer->children), layerGlobal); + std::string key = + base::StringPrintf("%s,%s,%s,%s,%s,%s,%s,%s,%s", + destinationLocation(layer->hwcFrame.left, + layerGlobal->resolution[0], true), + destinationLocation(layer->hwcFrame.top, + layerGlobal->resolution[1], false), + destinationSize(layer->hwcFrame.right - layer->hwcFrame.left, + layerGlobal->resolution[0], true), + destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top, + layerGlobal->resolution[1], false), + layer->type.c_str(), scaleRatioWH(layer.get()).c_str(), + layerTransform(layer->hwcTransform), layer->pixelFormat.c_str(), + layer->dataspace.c_str()); + mLayerStatsMap[key]++; + } +} + +void LayerStats::logLayerStats(const LayersProto& layersProto) { + ATRACE_CALL(); + auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto); + auto layerTree = LayerProtoParser::generateLayerTree(layersProto); + std::lock_guard lock(mMutex); + traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal); +} + +void LayerStats::dump(String8& result) { + ATRACE_CALL(); + ALOGD("Dumping"); + result.append("Count,DstPosX,DstPosY,DstWidth,DstHeight,LayerType,WScale,HScale,"); + result.append("Transform,PixelFormat,Dataspace\n"); + std::lock_guard lock(mMutex); + for (auto& u : mLayerStatsMap) { + result.appendFormat("%u,%s\n", u.second, u.first.c_str()); + } +} + +const char* LayerStats::destinationLocation(int32_t location, int32_t range, bool isHorizontal) { + static const char* locationArray[8] = {"0", "1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8"}; + int32_t ratio = location * 8 / range; + if (ratio < 0) return "N/A"; + if (isHorizontal) { + // X location is divided into 4 buckets {"0", "1/4", "1/2", "3/4"} + if (ratio > 6) return "3/4"; + // use index 0, 2, 4, 6 + return locationArray[ratio & ~1]; + } + if (ratio > 7) return "7/8"; + return locationArray[ratio]; +} + +const char* LayerStats::destinationSize(int32_t size, int32_t range, bool isWidth) { + static const char* sizeArray[8] = {"1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8", "1"}; + int32_t ratio = size * 8 / range; + if (ratio < 0) return "N/A"; + if (isWidth) { + // width is divided into 4 buckets {"1/4", "1/2", "3/4", "1"} + if (ratio > 6) return "1"; + // use index 1, 3, 5, 7 + return sizeArray[ratio | 1]; + } + if (ratio > 7) return "1"; + return sizeArray[ratio]; +} + +const char* LayerStats::layerTransform(int32_t transform) { + return getTransformName(static_cast(transform)); +} + +std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) { + if (!layer->type.compare("ColorLayer")) return "N/A,N/A"; + std::string ret = ""; + if (isRotated(layer->hwcTransform)) { + ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left, + static_cast(layer->hwcCrop.bottom - layer->hwcCrop.top)); + ret += ","; + ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top, + static_cast(layer->hwcCrop.right - layer->hwcCrop.left)); + } else { + ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left, + static_cast(layer->hwcCrop.right - layer->hwcCrop.left)); + ret += ","; + ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top, + static_cast(layer->hwcCrop.bottom - layer->hwcCrop.top)); + } + return ret; +} + +const char* LayerStats::scaleRatio(int32_t destinationScale, int32_t sourceScale) { + // Make scale buckets from <1/64 to >= 16, to avoid floating point + // calculation, x64 on destinationScale first + int32_t scale = destinationScale * 64 / sourceScale; + if (!scale) return "<1/64"; + if (scale < 2) return "1/64"; + if (scale < 4) return "1/32"; + if (scale < 8) return "1/16"; + if (scale < 16) return "1/8"; + if (scale < 32) return "1/4"; + if (scale < 64) return "1/2"; + if (scale < 128) return "1"; + if (scale < 256) return "2"; + if (scale < 512) return "4"; + if (scale < 1024) return "8"; + return ">=16"; +} + +bool LayerStats::isRotated(int32_t transform) { + return transform & HWC_TRANSFORM_ROT_90; +} + +bool LayerStats::isVFlipped(int32_t transform) { + return transform & HWC_TRANSFORM_FLIP_V; +} + +bool LayerStats::isHFlipped(int32_t transform) { + return transform & HWC_TRANSFORM_FLIP_H; +} + +} // namespace android diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h new file mode 100644 index 0000000000..de2b47c3ba --- /dev/null +++ b/services/surfaceflinger/LayerStats.h @@ -0,0 +1,69 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +using namespace android::surfaceflinger; + +namespace android { +class String8; + +class LayerStats { +public: + void enable(); + void disable(); + void clear(); + bool isEnabled(); + void logLayerStats(const LayersProto& layersProto); + void dump(String8& result); + +private: + // Traverse layer tree to get all visible layers' stats + void traverseLayerTreeStatsLocked( + std::vector> layerTree, + const LayerProtoParser::LayerGlobal* layerGlobal); + // Convert layer's top-left position into 8x8 percentage of the display + static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal); + // Convert layer's size into 8x8 percentage of the display + static const char* destinationSize(int32_t size, int32_t range, bool isWidth); + // Return the name of the transform + static const char* layerTransform(int32_t transform); + // Calculate scale ratios of layer's width/height with rotation information + static std::string scaleRatioWH(const LayerProtoParser::Layer* layer); + // Calculate scale ratio from source to destination and convert to string + static const char* scaleRatio(int32_t destinationScale, int32_t sourceScale); + // Return whether the original buffer is rotated in final composition + static bool isRotated(int32_t transform); + // Return whether the original buffer is V-flipped in final composition + static bool isVFlipped(int32_t transform); + // Return whether the original buffer is H-flipped in final composition + static bool isHFlipped(int32_t transform); + + bool mEnabled = false; + // Protect mLayersStatsMap + std::mutex mMutex; + // Hashmap for tracking the layer stats + // KEY is a concatenation of a particular set of layer properties + // VALUE is the number of times this particular get scanned out + std::unordered_map mLayerStatsMap; +}; + +} // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f180a3b285..babac37d7d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1484,6 +1484,7 @@ void SurfaceFlinger::handleMessageRefresh() { setUpHWComposer(); doDebugFlashRegions(); doTracing("handleRefresh"); + logLayerStats(); doComposition(); postComposition(refreshStartTime); @@ -1553,6 +1554,25 @@ void SurfaceFlinger::doTracing(const char* where) { } } +void SurfaceFlinger::logLayerStats() { + ATRACE_CALL(); + if (CC_UNLIKELY(mLayerStats.isEnabled())) { + int32_t hwcId = -1; + for (size_t dpy = 0; dpy < mDisplays.size(); ++dpy) { + const sp& displayDevice(mDisplays[dpy]); + if (displayDevice->isPrimary()) { + hwcId = displayDevice->getHwcDisplayId(); + break; + } + } + if (hwcId < 0) { + ALOGE("LayerStats: Hmmm, no primary display?"); + return; + } + mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(hwcId)); + } +} + void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) { ATRACE_CALL(); @@ -3772,6 +3792,34 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro dumpWideColorInfo(result); dumpAll = false; } + + if ((index < numArgs) && + (args[index] == String16("--enable-layer-stats"))) { + index++; + mLayerStats.enable(); + dumpAll = false; + } + + if ((index < numArgs) && + (args[index] == String16("--disable-layer-stats"))) { + index++; + mLayerStats.disable(); + dumpAll = false; + } + + if ((index < numArgs) && + (args[index] == String16("--clear-layer-stats"))) { + index++; + mLayerStats.clear(); + dumpAll = false; + } + + if ((index < numArgs) && + (args[index] == String16("--dump-layer-stats"))) { + index++; + mLayerStats.dump(result); + dumpAll = false; + } } if (dumpAll) { @@ -3979,6 +4027,25 @@ LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const return layersProto; } +LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(int32_t hwcId) const { + LayersProto layersProto; + + const sp& displayDevice(mDisplays[hwcId]); + SizeProto* resolution = layersProto.mutable_resolution(); + resolution->set_w(displayDevice->getWidth()); + resolution->set_h(displayDevice->getHeight()); + + mDrawingState.traverseInZOrder([&](Layer* layer) { + if (!layer->visibleRegion.isEmpty() && + layer->getBE().mHwcLayers.count(hwcId)) { + LayerProto* layerProto = layersProto.add_layers(); + layer->writeToProto(layerProto, hwcId); + } + }); + + return layersProto; +} + void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, String8& result) const { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 448509bc8f..c7c308883b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -55,6 +55,7 @@ #include "DisplayDevice.h" #include "DispSync.h" #include "FrameTracker.h" +#include "LayerStats.h" #include "LayerVector.h" #include "MessageQueue.h" #include "SurfaceInterceptor.h" @@ -645,6 +646,7 @@ private: void doComposition(); void doDebugFlashRegions(); void doTracing(const char* where); + void logLayerStats(); void doDisplayComposition(const sp& displayDevice, const Region& dirtyRegion); // compose surfaces for display hw. this fails if using GL and the surface @@ -711,6 +713,7 @@ private: void dumpBufferingStats(String8& result) const; void dumpWideColorInfo(String8& result) const; LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const; + LayersProto dumpVisibleLayersProtoInfo(int32_t hwcId) const; bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; @@ -797,6 +800,7 @@ private: std::unique_ptr mInterceptor = std::make_unique(this); SurfaceTracing mTracing; + LayerStats mLayerStats; bool mUseHwcVirtualDisplays = false; // Restrict layers to use two buffers in their bufferqueues. diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index 1383d288b9..cef6c21eb1 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -42,6 +42,11 @@ bool sortLayerUniquePtrs(const std::unique_ptr& lhs, return sortLayers(lhs.get(), rhs.get()); } +const LayerProtoParser::LayerGlobal LayerProtoParser::generateLayerGlobalInfo( + const LayersProto& layersProto) { + return {{layersProto.resolution().w(), layersProto.resolution().h()}}; +} + std::vector> LayerProtoParser::generateLayerTree( const LayersProto& layersProto) { std::unordered_map layerMap = generateMap(layersProto); @@ -106,6 +111,9 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer()); layer->queuedFrames = layerProto.queued_frames(); layer->refreshPending = layerProto.refresh_pending(); + layer->hwcFrame = generateRect(layerProto.hwc_frame()); + layer->hwcCrop = generateFloatRect(layerProto.hwc_crop()); + layer->hwcTransform = layerProto.hwc_transform(); layer->windowType = layerProto.window_type(); layer->appId = layerProto.app_id(); @@ -133,6 +141,16 @@ LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto return rect; } +LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect(const FloatRectProto& rectProto) { + LayerProtoParser::FloatRect rect; + rect.left = rectProto.left(); + rect.top = rectProto.top(); + rect.right = rectProto.right(); + rect.bottom = rectProto.bottom(); + + return rect; +} + LayerProtoParser::Transform LayerProtoParser::generateTransform( const TransformProto& transformProto) { LayerProtoParser::Transform transform; @@ -246,6 +264,10 @@ std::string LayerProtoParser::Rect::to_string() const { return StringPrintf("[%3d, %3d, %3d, %3d]", left, top, right, bottom); } +std::string LayerProtoParser::FloatRect::to_string() const { + return StringPrintf("[%.2f, %.2f, %.2f, %.2f]", left, top, right, bottom); +} + std::string LayerProtoParser::Region::to_string(const char* what) const { std::string result = StringPrintf(" Region %s (this=%lx count=%d)\n", what, static_cast(id), diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index b56a6fbb97..fd893da1b1 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#pragma once #include @@ -57,6 +58,16 @@ public: std::string to_string() const; }; + class FloatRect { + public: + float left; + float top; + float right; + float bottom; + + std::string to_string() const; + }; + class Region { public: uint64_t id; @@ -96,12 +107,21 @@ public: LayerProtoParser::ActiveBuffer activeBuffer; int32_t queuedFrames; bool refreshPending; + LayerProtoParser::Rect hwcFrame; + LayerProtoParser::FloatRect hwcCrop; + int32_t hwcTransform; int32_t windowType; int32_t appId; std::string to_string() const; }; + class LayerGlobal { + public: + int2 resolution; + }; + + static const LayerGlobal generateLayerGlobalInfo(const LayersProto& layersProto); static std::vector> generateLayerTree(const LayersProto& layersProto); static std::string layersToString(std::vector> layers); @@ -110,6 +130,7 @@ private: static LayerProtoParser::Layer* generateLayer(const LayerProto& layerProto); static LayerProtoParser::Region generateRegion(const RegionProto& regionProto); static LayerProtoParser::Rect generateRect(const RectProto& rectProto); + static LayerProtoParser::FloatRect generateFloatRect(const FloatRectProto& rectProto); static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto); static LayerProtoParser::ActiveBuffer generateActiveBuffer( const ActiveBufferProto& activeBufferProto); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index f18386b1ac..6675aae797 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -7,6 +7,7 @@ package android.surfaceflinger; // Contains a list of all layers. message LayersProto { repeated LayerProto layers = 1; + optional SizeProto resolution = 2; } // Information about each layer. @@ -64,8 +65,14 @@ message LayerProto { // The number of frames available. optional int32 queued_frames = 28; optional bool refresh_pending = 29; - optional int32 window_type = 30; - optional int32 app_id = 31; + // The layer's composer backend destination frame + optional RectProto hwc_frame = 30; + // The layer's composer backend source crop + optional FloatRectProto hwc_crop = 31; + // The layer's composer backend transform + optional int32 hwc_transform = 32; + optional int32 window_type = 33; + optional int32 app_id = 34; } message PositionProto { @@ -97,6 +104,13 @@ message RectProto { optional int32 bottom = 4; } +message FloatRectProto { + optional float left = 1; + optional float top = 2; + optional float right = 3; + optional float bottom = 4; +} + message ActiveBufferProto { optional uint32 width = 1; optional uint32 height = 2; @@ -109,4 +123,4 @@ message ColorProto { optional float g = 2; optional float b = 3; optional float a = 4; -} \ No newline at end of file +} -- cgit v1.2.3-59-g8ed1b From 7c64f17bd0d70aec63b475c3de850dcf3abaff33 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 7 Mar 2018 14:52:28 -0800 Subject: Implement Display Layer Stats V0.1 Try to collect data for analyzing how many display controller layers we need and what we use them for. This change will collect additional data from per frame point of view. Test: adb shell dumpsys SurfaceFlinger --enable-layer-stats Test: adb shell dumpsys SurfaceFlinger --disable-layer-stats Test: adb shell dumpsys SurfaceFlinger --clear-layer-stats Test: adb shell dumpsys SurfaceFlinger --dump-layer-stats Bug: b/75953772 Change-Id: Ib48777df7e1fed637be7eb1aefbdf1808d1daccd Merged-In: Ib48777df7e1fed637be7eb1aefbdf1808d1daccd --- libs/ui/DebugUtils.cpp | 27 ++++++ libs/ui/include/ui/DebugUtils.h | 1 + services/surfaceflinger/DisplayDevice.cpp | 11 +++ services/surfaceflinger/DisplayDevice.h | 6 ++ services/surfaceflinger/Layer.cpp | 11 +++ services/surfaceflinger/LayerStats.cpp | 97 +++++++++++++++++----- services/surfaceflinger/LayerStats.h | 19 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 11 ++- .../surfaceflinger/layerproto/LayerProtoParser.cpp | 9 +- .../include/layerproto/LayerProtoParser.h | 5 ++ services/surfaceflinger/layerproto/layers.proto | 7 ++ 11 files changed, 171 insertions(+), 33 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp index d7d8618703..58fed84ea8 100644 --- a/libs/ui/DebugUtils.cpp +++ b/libs/ui/DebugUtils.cpp @@ -234,6 +234,33 @@ std::string decodeColorMode(ColorMode colorMode) { return android::base::StringPrintf("Unknown color mode %d", colorMode); } +std::string decodeColorTransform(android_color_transform colorTransform) { + switch (colorTransform) { + case HAL_COLOR_TRANSFORM_IDENTITY: + return std::string("Identity"); + + case HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX: + return std::string("Arbitrary matrix"); + + case HAL_COLOR_TRANSFORM_VALUE_INVERSE: + return std::string("Inverse value"); + + case HAL_COLOR_TRANSFORM_GRAYSCALE: + return std::string("Grayscale"); + + case HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA: + return std::string("Correct protanopia"); + + case HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA: + return std::string("Correct deuteranopia"); + + case HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA: + return std::string("Correct tritanopia"); + } + + return android::base::StringPrintf("Unknown color transform %d", colorTransform); +} + // Converts a PixelFormat to a human-readable string. Max 11 chars. // (Could use a table of prefab String8 objects.) std::string decodePixelFormat(android::PixelFormat format) { diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h index 6350d0cf95..5e5df43740 100644 --- a/libs/ui/include/ui/DebugUtils.h +++ b/libs/ui/include/ui/DebugUtils.h @@ -30,5 +30,6 @@ std::string decodeTransfer(android_dataspace dataspace); std::string decodeRange(android_dataspace dataspace); std::string dataspaceDetails(android_dataspace dataspace); std::string decodeColorMode(android::ui::ColorMode colormode); +std::string decodeColorTransform(android_color_transform colorTransform); std::string decodePixelFormat(android::PixelFormat format); std::string to_string(const android::Rect& rect); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 93cb849e28..8281ce0f56 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -97,6 +97,7 @@ DisplayDevice::DisplayDevice( mPowerMode(initialPowerMode), mActiveConfig(0), mActiveColorMode(ColorMode::NATIVE), + mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY), mDisplayHasWideColor(supportWideColor), mDisplayHasHdr(supportHdr) { @@ -267,6 +268,16 @@ ColorMode DisplayDevice::getActiveColorMode() const { return mActiveColorMode; } +void DisplayDevice::setColorTransform(const mat4& transform) { + const bool isIdentity = (transform == mat4()); + mColorTransform = + isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX; +} + +android_color_transform_t DisplayDevice::getColorTransform() const { + return mColorTransform; +} + void DisplayDevice::setCompositionDataSpace(android_dataspace dataspace) { ANativeWindow* const window = mNativeWindow.get(); native_window_set_buffers_data_space(window, dataspace); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index df729f5ce9..31bb4d0778 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -21,6 +21,8 @@ #include +#include + #include #include @@ -163,6 +165,8 @@ public: ui::ColorMode getActiveColorMode() const; void setActiveColorMode(ui::ColorMode mode); + android_color_transform_t getColorTransform() const; + void setColorTransform(const mat4& transform); void setCompositionDataSpace(android_dataspace dataspace); /* ------------------------------------------------------------------------ @@ -237,6 +241,8 @@ private: int mActiveConfig; // current active color mode ui::ColorMode mActiveColorMode; + // Current color transform + android_color_transform_t mColorTransform; // Need to know if display is wide-color capable or not. // Initialized by SurfaceFlinger when the DisplayDevice is created. diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c3eb1bc85f..5c945edb5f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -42,6 +42,7 @@ #include #include +#include "BufferLayer.h" #include "Colorizer.h" #include "DisplayDevice.h" #include "Layer.h" @@ -1937,6 +1938,16 @@ void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) { const int32_t transform = static_cast(hwcInfo.transform); layerInfo->set_hwc_transform(transform); + + const int32_t compositionType = static_cast(hwcInfo.compositionType); + layerInfo->set_hwc_composition_type(compositionType); + + if (std::strcmp(getTypeId(), "BufferLayer") == 0 && + static_cast(this)->isProtected()) { + layerInfo->set_is_protected(true); + } else { + layerInfo->set_is_protected(false); + } } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp index dc99b41cc6..38ea6edfc5 100644 --- a/services/surfaceflinger/LayerStats.cpp +++ b/services/surfaceflinger/LayerStats.cpp @@ -19,6 +19,7 @@ #include "LayerStats.h" #include "DisplayHardware/HWComposer.h" +#include "ui/DebugUtils.h" #include #include @@ -31,7 +32,7 @@ void LayerStats::enable() { ATRACE_CALL(); std::lock_guard lock(mMutex); if (mEnabled) return; - mLayerStatsMap.clear(); + mLayerShapeStatsMap.clear(); mEnabled = true; ALOGD("Logging enabled"); } @@ -47,7 +48,7 @@ void LayerStats::disable() { void LayerStats::clear() { ATRACE_CALL(); std::lock_guard lock(mMutex); - mLayerStatsMap.clear(); + mLayerShapeStatsMap.clear(); ALOGD("Cleared current layer stats"); } @@ -57,42 +58,69 @@ bool LayerStats::isEnabled() { void LayerStats::traverseLayerTreeStatsLocked( std::vector> layerTree, - const LayerProtoParser::LayerGlobal* layerGlobal) { + const LayerProtoParser::LayerGlobal* layerGlobal, std::vector& layerShapeVec) { for (std::unique_ptr& layer : layerTree) { if (!layer) continue; - traverseLayerTreeStatsLocked(std::move(layer->children), layerGlobal); - std::string key = - base::StringPrintf("%s,%s,%s,%s,%s,%s,%s,%s,%s", - destinationLocation(layer->hwcFrame.left, - layerGlobal->resolution[0], true), - destinationLocation(layer->hwcFrame.top, - layerGlobal->resolution[1], false), - destinationSize(layer->hwcFrame.right - layer->hwcFrame.left, - layerGlobal->resolution[0], true), - destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top, - layerGlobal->resolution[1], false), - layer->type.c_str(), scaleRatioWH(layer.get()).c_str(), - layerTransform(layer->hwcTransform), layer->pixelFormat.c_str(), - layer->dataspace.c_str()); - mLayerStatsMap[key]++; + traverseLayerTreeStatsLocked(std::move(layer->children), layerGlobal, layerShapeVec); + std::string key = ""; + base::StringAppendF(&key, ",%s", layer->type.c_str()); + base::StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType)); + base::StringAppendF(&key, ",%d", layer->isProtected); + base::StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform)); + base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format)); + base::StringAppendF(&key, ",%s", layer->dataspace.c_str()); + base::StringAppendF(&key, ",%s", + destinationLocation(layer->hwcFrame.left, layerGlobal->resolution[0], + true)); + base::StringAppendF(&key, ",%s", + destinationLocation(layer->hwcFrame.top, layerGlobal->resolution[1], + false)); + base::StringAppendF(&key, ",%s", + destinationSize(layer->hwcFrame.right - layer->hwcFrame.left, + layerGlobal->resolution[0], true)); + base::StringAppendF(&key, ",%s", + destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top, + layerGlobal->resolution[1], false)); + base::StringAppendF(&key, ",%s", scaleRatioWH(layer.get()).c_str()); + base::StringAppendF(&key, ",%s", alpha(static_cast(layer->color.a))); + + layerShapeVec.push_back(key); + ALOGV("%s", key.c_str()); } } void LayerStats::logLayerStats(const LayersProto& layersProto) { ATRACE_CALL(); + ALOGV("Logging"); auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto); auto layerTree = LayerProtoParser::generateLayerTree(layersProto); + std::vector layerShapeVec; + std::lock_guard lock(mMutex); - traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal); + traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal, layerShapeVec); + + std::string layerShapeKey = + base::StringPrintf("%d,%s,%s,%s", static_cast(layerShapeVec.size()), + layerGlobal.colorMode.c_str(), layerGlobal.colorTransform.c_str(), + layerTransform(layerGlobal.globalTransform)); + ALOGV("%s", layerShapeKey.c_str()); + + std::sort(layerShapeVec.begin(), layerShapeVec.end(), std::greater()); + for (auto const& s : layerShapeVec) { + layerShapeKey += s; + } + + mLayerShapeStatsMap[layerShapeKey]++; } void LayerStats::dump(String8& result) { ATRACE_CALL(); ALOGD("Dumping"); - result.append("Count,DstPosX,DstPosY,DstWidth,DstHeight,LayerType,WScale,HScale,"); - result.append("Transform,PixelFormat,Dataspace\n"); std::lock_guard lock(mMutex); - for (auto& u : mLayerStatsMap) { + result.append("Frequency,LayerCount,ColorMode,ColorTransform,Orientation\n"); + result.append("LayerType,CompositionType,IsProtected,Transform,PixelFormat,Dataspace,"); + result.append("DstX,DstY,DstWidth,DstHeight,WScale,HScale,Alpha\n"); + for (auto& u : mLayerShapeStatsMap) { result.appendFormat("%u,%s\n", u.second, u.first.c_str()); } } @@ -129,6 +157,14 @@ const char* LayerStats::layerTransform(int32_t transform) { return getTransformName(static_cast(transform)); } +const char* LayerStats::layerCompositionType(int32_t compositionType) { + return getCompositionName(static_cast(compositionType)); +} + +const char* LayerStats::layerPixelFormat(int32_t pixelFormat) { + return decodePixelFormat(pixelFormat).c_str(); +} + std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) { if (!layer->type.compare("ColorLayer")) return "N/A,N/A"; std::string ret = ""; @@ -166,6 +202,21 @@ const char* LayerStats::scaleRatio(int32_t destinationScale, int32_t sourceScale return ">=16"; } +const char* LayerStats::alpha(float a) { + if (a == 1.0f) return "1.0"; + if (a > 0.9f) return "0.99"; + if (a > 0.8f) return "0.9"; + if (a > 0.7f) return "0.8"; + if (a > 0.6f) return "0.7"; + if (a > 0.5f) return "0.6"; + if (a > 0.4f) return "0.5"; + if (a > 0.3f) return "0.4"; + if (a > 0.2f) return "0.3"; + if (a > 0.1f) return "0.2"; + if (a > 0.0f) return "0.1"; + return "0.0"; +} + bool LayerStats::isRotated(int32_t transform) { return transform & HWC_TRANSFORM_ROT_90; } @@ -178,4 +229,4 @@ bool LayerStats::isHFlipped(int32_t transform) { return transform & HWC_TRANSFORM_FLIP_H; } -} // namespace android +} // namespace android diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h index de2b47c3ba..7871fc6602 100644 --- a/services/surfaceflinger/LayerStats.h +++ b/services/surfaceflinger/LayerStats.h @@ -39,17 +39,24 @@ private: // Traverse layer tree to get all visible layers' stats void traverseLayerTreeStatsLocked( std::vector> layerTree, - const LayerProtoParser::LayerGlobal* layerGlobal); + const LayerProtoParser::LayerGlobal* layerGlobal, + std::vector& layerShapeVec); // Convert layer's top-left position into 8x8 percentage of the display static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal); // Convert layer's size into 8x8 percentage of the display static const char* destinationSize(int32_t size, int32_t range, bool isWidth); // Return the name of the transform static const char* layerTransform(int32_t transform); + // Return the name of the composition type + static const char* layerCompositionType(int32_t compositionType); + // Return the name of the pixel format + static const char* layerPixelFormat(int32_t pixelFormat); // Calculate scale ratios of layer's width/height with rotation information static std::string scaleRatioWH(const LayerProtoParser::Layer* layer); // Calculate scale ratio from source to destination and convert to string static const char* scaleRatio(int32_t destinationScale, int32_t sourceScale); + // Bucket the alpha into designed buckets + static const char* alpha(float a); // Return whether the original buffer is rotated in final composition static bool isRotated(int32_t transform); // Return whether the original buffer is V-flipped in final composition @@ -60,10 +67,10 @@ private: bool mEnabled = false; // Protect mLayersStatsMap std::mutex mMutex; - // Hashmap for tracking the layer stats - // KEY is a concatenation of a particular set of layer properties - // VALUE is the number of times this particular get scanned out - std::unordered_map mLayerStatsMap; + // Hashmap for tracking the frame(layer shape) stats + // KEY is a concatenation of all layers' properties within a frame + // VALUE is the number of times this particular set has been scanned out + std::unordered_map mLayerShapeStatsMap; }; -} // namespace android +} // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index babac37d7d..f7f5b58616 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1960,6 +1960,7 @@ void SurfaceFlinger::setUpHWComposer() { continue; } if (colorMatrix != mPreviousColorMatrix) { + displayDevice->setColorTransform(colorMatrix); status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix); ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " "display %zd: %d", displayId, result); @@ -4029,15 +4030,19 @@ LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(int32_t hwcId) const { LayersProto layersProto; - const sp& displayDevice(mDisplays[hwcId]); + SizeProto* resolution = layersProto.mutable_resolution(); resolution->set_w(displayDevice->getWidth()); resolution->set_h(displayDevice->getHeight()); + layersProto.set_color_mode(decodeColorMode(displayDevice->getActiveColorMode())); + layersProto.set_color_transform(decodeColorTransform(displayDevice->getColorTransform())); + layersProto.set_global_transform( + static_cast(displayDevice->getOrientationTransform())); + mDrawingState.traverseInZOrder([&](Layer* layer) { - if (!layer->visibleRegion.isEmpty() && - layer->getBE().mHwcLayers.count(hwcId)) { + if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(hwcId)) { LayerProto* layerProto = layersProto.add_layers(); layer->writeToProto(layerProto, hwcId); } diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index cef6c21eb1..fcf42f00a9 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -44,7 +44,12 @@ bool sortLayerUniquePtrs(const std::unique_ptr& lhs, const LayerProtoParser::LayerGlobal LayerProtoParser::generateLayerGlobalInfo( const LayersProto& layersProto) { - return {{layersProto.resolution().w(), layersProto.resolution().h()}}; + LayerGlobal layerGlobal; + layerGlobal.resolution = {layersProto.resolution().w(), layersProto.resolution().h()}; + layerGlobal.colorMode = layersProto.color_mode(); + layerGlobal.colorTransform = layersProto.color_transform(); + layerGlobal.globalTransform = layersProto.global_transform(); + return layerGlobal; } std::vector> LayerProtoParser::generateLayerTree( @@ -116,6 +121,8 @@ LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layer layer->hwcTransform = layerProto.hwc_transform(); layer->windowType = layerProto.window_type(); layer->appId = layerProto.app_id(); + layer->hwcCompositionType = layerProto.hwc_composition_type(); + layer->isProtected = layerProto.is_protected(); return layer; } diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index fd893da1b1..74a6f28f2b 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -112,6 +112,8 @@ public: int32_t hwcTransform; int32_t windowType; int32_t appId; + int32_t hwcCompositionType; + bool isProtected; std::string to_string() const; }; @@ -119,6 +121,9 @@ public: class LayerGlobal { public: int2 resolution; + std::string colorMode; + std::string colorTransform; + int32_t globalTransform; }; static const LayerGlobal generateLayerGlobalInfo(const LayersProto& layersProto); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 6675aae797..77c6675b7f 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -8,6 +8,9 @@ package android.surfaceflinger; message LayersProto { repeated LayerProto layers = 1; optional SizeProto resolution = 2; + optional string color_mode = 3; + optional string color_transform = 4; + optional int32 global_transform = 5; } // Information about each layer. @@ -73,6 +76,10 @@ message LayerProto { optional int32 hwc_transform = 32; optional int32 window_type = 33; optional int32 app_id = 34; + // The layer's composition type + optional int32 hwc_composition_type = 35; + // If it's a buffer layer, indicate if the content is protected + optional bool is_protected = 36; } message PositionProto { -- cgit v1.2.3-59-g8ed1b From 34beb7a0ff0494b0c5ad81104171f8a49e599163 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 28 Mar 2018 11:57:12 -0700 Subject: [SurfaceFlinger] Replace android_dataspace with Dataspace. This patch replaces all android_dataspace in SurfaceFlinger with Dataspace V1.1. 3 commands in sequence are used to do the conversion: find ./ -type f -exec sed -i -e 's/android_dataspace_t/Dataspace/g' {} \; find ./ -type f -exec sed -i -e 's/android_dataspace/Dataspace/g' {} \; find ./ -type f -exec sed -i -e 's/HAL_DATASPACE_/Dataspace::/g' {} \; With some minor tweak because most of the APIs in frameworks/native are still accepting android_dataspace/android_dataspace_t. Next step is to convert the rest of android_dataspace usage to Dataspace in frameworks/native as well as frameworks/base. BUG: 77156734 Test: Build and flash Change-Id: I2304c7014cb49a1c9f67c4563603fb55e8dbd679 --- libs/gui/Surface.cpp | 15 +-- libs/gui/include/gui/Surface.h | 9 +- libs/ui/include/ui/GraphicTypes.h | 2 + services/surfaceflinger/BufferLayer.cpp | 2 +- services/surfaceflinger/BufferLayerConsumer.cpp | 6 +- services/surfaceflinger/BufferLayerConsumer.h | 5 +- services/surfaceflinger/DisplayDevice.cpp | 9 +- services/surfaceflinger/DisplayDevice.h | 2 +- .../surfaceflinger/DisplayHardware/ComposerHal.cpp | 40 +++++--- .../surfaceflinger/DisplayHardware/ComposerHal.h | 5 +- .../DisplayHardware/FramebufferSurface.cpp | 11 ++- .../DisplayHardware/FramebufferSurface.h | 4 +- services/surfaceflinger/DisplayHardware/HWC2.cpp | 23 +++-- services/surfaceflinger/DisplayHardware/HWC2.h | 8 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 4 +- .../surfaceflinger/DisplayHardware/HWComposer.h | 4 +- .../DisplayHardware/VirtualDisplaySurface.cpp | 2 +- services/surfaceflinger/Layer.cpp | 10 +- services/surfaceflinger/Layer.h | 6 +- .../RenderEngine/GLES20RenderEngine.cpp | 22 +++-- .../RenderEngine/GLES20RenderEngine.h | 8 +- .../surfaceflinger/RenderEngine/RenderEngine.h | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 62 ++++++------ services/surfaceflinger/SurfaceFlinger.h | 4 +- services/surfaceflinger/tests/hwc2/Android.bp | 1 + services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 19 ++-- .../tests/hwc2/Hwc2TestClientTarget.cpp | 2 +- .../tests/hwc2/Hwc2TestClientTarget.h | 2 +- .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 2 +- services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 2 +- .../surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp | 2 +- .../surfaceflinger/tests/hwc2/Hwc2TestLayers.h | 2 +- .../tests/hwc2/Hwc2TestProperties.cpp | 106 ++++++++++----------- .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 9 +- .../surfaceflinger/tests/unittests/MockComposer.h | 4 +- .../tests/unittests/MockRenderEngine.h | 4 +- 36 files changed, 226 insertions(+), 196 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 6a1aebd6d6..339bd0fa4e 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -45,6 +45,7 @@ namespace android { using ui::ColorMode; +using ui::Dataspace; Surface::Surface(const sp& bufferProducer, bool controlledByApp) : mGraphicBufferProducer(bufferProducer), @@ -80,7 +81,7 @@ Surface::Surface(const sp& bufferProducer, bool controll mReqFormat = 0; mReqUsage = 0; mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO; - mDataSpace = HAL_DATASPACE_UNKNOWN; + mDataSpace = Dataspace::UNKNOWN; mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; mTransform = 0; mStickyTransform = 0; @@ -666,8 +667,9 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { sp fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); IGraphicBufferProducer::QueueBufferOutput output; IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp, - mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform, - fence, mStickyTransform, mEnableFrameTimestamps); + static_cast(mDataSpace), crop, mScalingMode, + mTransform ^ mStickyTransform, fence, mStickyTransform, + mEnableFrameTimestamps); // we should send HDR metadata as needed if this becomes a bottleneck input.setHdrMetadata(mHdrMetadata); @@ -1098,8 +1100,7 @@ int Surface::dispatchSetSidebandStream(va_list args) { } int Surface::dispatchSetBuffersDataSpace(va_list args) { - android_dataspace dataspace = - static_cast(va_arg(args, int)); + Dataspace dataspace = static_cast(va_arg(args, int)); return setBuffersDataSpace(dataspace); } @@ -1531,7 +1532,7 @@ int Surface::setBuffersTimestamp(int64_t timestamp) return NO_ERROR; } -int Surface::setBuffersDataSpace(android_dataspace dataSpace) +int Surface::setBuffersDataSpace(Dataspace dataSpace) { ALOGV("Surface::setBuffersDataSpace"); Mutex::Autolock lock(mMutex); @@ -1563,7 +1564,7 @@ int Surface::setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata return NO_ERROR; } -android_dataspace_t Surface::getBuffersDataSpace() { +Dataspace Surface::getBuffersDataSpace() { ALOGV("Surface::getBuffersDataSpace"); Mutex::Autolock lock(mMutex); return mDataSpace; diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 641d62cd4d..9aeafae198 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -245,7 +246,7 @@ protected: virtual int setBuffersTransform(uint32_t transform); virtual int setBuffersStickyTransform(uint32_t transform); virtual int setBuffersTimestamp(int64_t timestamp); - virtual int setBuffersDataSpace(android_dataspace dataSpace); + virtual int setBuffersDataSpace(ui::Dataspace dataSpace); virtual int setBuffersSmpte2086Metadata(const android_smpte2086_metadata* metadata); virtual int setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata); virtual int setCrop(Rect const* rect); @@ -286,7 +287,7 @@ public: // detachNextBuffer, or attachBuffer call. status_t getAndFlushRemovedBuffers(std::vector>* out); - android_dataspace_t getBuffersDataSpace(); + ui::Dataspace getBuffersDataSpace(); static status_t attachAndQueueBuffer(Surface* surface, sp buffer); @@ -340,9 +341,9 @@ protected: int64_t mTimestamp; // mDataSpace is the buffer dataSpace that will be used for the next buffer - // queue operation. It defaults to HAL_DATASPACE_UNKNOWN, which + // queue operation. It defaults to Dataspace::UNKNOWN, which // means that the buffer contains some type of color data. - android_dataspace mDataSpace; + ui::Dataspace mDataSpace; // mHdrMetadata is the HDR metadata that will be used for the next buffer // queue operation. There is no HDR metadata by default. diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h index 39893b268a..92a5519898 100644 --- a/libs/ui/include/ui/GraphicTypes.h +++ b/libs/ui/include/ui/GraphicTypes.h @@ -25,6 +25,8 @@ namespace android { namespace ui { using android::hardware::graphics::common::V1_0::ColorMode; +using android::hardware::graphics::common::V1_1::Dataspace; +using android::hardware::graphics::common::V1_1::PixelFormat; } // namespace ui } // namespace android diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 9200207f4a..82300e679f 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -829,7 +829,7 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT getColor()); engine.setSourceDataSpace(mCurrentState.dataSpace); - if (mCurrentState.dataSpace == HAL_DATASPACE_BT2020_ITU_PQ && + if (mCurrentState.dataSpace == ui::Dataspace::BT2020_ITU_PQ && mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA && getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) { engine.setSourceY410BT2020(true); diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 46ec0e322b..6b4f5dbfb0 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -65,7 +65,7 @@ BufferLayerConsumer::BufferLayerConsumer(const sp& bq, mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mCurrentFence(Fence::NO_FENCE), mCurrentTimestamp(0), - mCurrentDataSpace(HAL_DATASPACE_UNKNOWN), + mCurrentDataSpace(ui::Dataspace::UNKNOWN), mCurrentFrameNumber(0), mCurrentTransformToDisplayInverse(false), mCurrentSurfaceDamage(), @@ -341,7 +341,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, mCurrentTransform = item.mTransform; mCurrentScalingMode = item.mScalingMode; mCurrentTimestamp = item.mTimestamp; - mCurrentDataSpace = item.mDataSpace; + mCurrentDataSpace = static_cast(item.mDataSpace); mCurrentHdrMetadata = item.mHdrMetadata; mCurrentFence = item.mFence; mCurrentFenceTime = item.mFenceTime; @@ -445,7 +445,7 @@ nsecs_t BufferLayerConsumer::getTimestamp() { return mCurrentTimestamp; } -android_dataspace BufferLayerConsumer::getCurrentDataSpace() { +ui::Dataspace BufferLayerConsumer::getCurrentDataSpace() { BLC_LOGV("getCurrentDataSpace"); Mutex::Autolock lock(mMutex); return mCurrentDataSpace; diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index 11048d8df8..f81cdb1d91 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -122,7 +123,7 @@ public: // getDataSpace retrieves the DataSpace associated with the texture image // set by the most recent call to updateTexImage. - android_dataspace getCurrentDataSpace(); + ui::Dataspace getCurrentDataSpace(); // getCurrentHdrMetadata retrieves the HDR metadata associated with the // texture image set by the most recent call to updateTexImage. @@ -324,7 +325,7 @@ private: // mCurrentDataSpace is the dataspace for the current texture. It // gets set each time updateTexImage is called. - android_dataspace mCurrentDataSpace; + ui::Dataspace mCurrentDataSpace; // mCurrentHdrMetadata is the HDR metadata for the current texture. It // gets set each time updateTexImage is called. diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 8281ce0f56..58a774b7e2 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -278,9 +278,9 @@ android_color_transform_t DisplayDevice::getColorTransform() const { return mColorTransform; } -void DisplayDevice::setCompositionDataSpace(android_dataspace dataspace) { +void DisplayDevice::setCompositionDataSpace(ui::Dataspace dataspace) { ANativeWindow* const window = mNativeWindow.get(); - native_window_set_buffers_data_space(window, dataspace); + native_window_set_buffers_data_space(window, static_cast(dataspace)); } // ---------------------------------------------------------------------------- @@ -463,12 +463,11 @@ void DisplayDevice::dump(String8& result) const { mScissor.top, mScissor.right, mScissor.bottom, tr[0][0], tr[1][0], tr[2][0], tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]); auto const surface = static_cast(window); - android_dataspace dataspace = surface->getBuffersDataSpace(); + ui::Dataspace dataspace = surface->getBuffersDataSpace(); result.appendFormat(" wideColor=%d, hdr=%d, colorMode=%s, dataspace: %s (%d)\n", mDisplayHasWideColor, mDisplayHasHdr, decodeColorMode(mActiveColorMode).c_str(), - dataspaceDetails(dataspace).c_str(), dataspace); - + dataspaceDetails(static_cast(dataspace)).c_str(), dataspace); String8 surfaceDump; mDisplaySurface->dumpAsString(surfaceDump); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 31bb4d0778..e844d115c2 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -167,7 +167,7 @@ public: void setActiveColorMode(ui::ColorMode mode); android_color_transform_t getColorTransform() const; void setColorTransform(const mat4& transform); - void setCompositionDataSpace(android_dataspace dataspace); + void setCompositionDataSpace(ui::Dataspace dataspace); /* ------------------------------------------------------------------------ * Display active config management. diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index 117a99db79..bbffd0ae7f 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -32,6 +32,7 @@ namespace android { using hardware::Return; using hardware::hidl_vec; using hardware::hidl_handle; +using namespace hardware::graphics::common; using namespace hardware::graphics::composer; using PerFrameMetadata = hardware::graphics::composer::V2_2::IComposerClient::PerFrameMetadata; using PerFrameMetadataKey = @@ -256,17 +257,32 @@ Error Composer::createVirtualDisplay(uint32_t width, uint32_t height, { const uint32_t bufferSlotCount = 1; Error error = kDefaultError; - mClient->createVirtualDisplay(width, height, *format, bufferSlotCount, - [&](const auto& tmpError, const auto& tmpDisplay, - const auto& tmpFormat) { - error = tmpError; - if (error != Error::NONE) { - return; - } - - *outDisplay = tmpDisplay; - *format = tmpFormat; + if (mClient_2_2) { + mClient_2_2->createVirtualDisplay_2_2(width, height, *format, bufferSlotCount, + [&](const auto& tmpError, const auto& tmpDisplay, + const auto& tmpFormat) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outDisplay = tmpDisplay; + *format = tmpFormat; + }); + } else { + mClient->createVirtualDisplay(width, height, + static_cast(*format), bufferSlotCount, + [&](const auto& tmpError, const auto& tmpDisplay, + const auto& tmpFormat) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outDisplay = tmpDisplay; + *format = static_cast(tmpFormat); }); + } return error; } @@ -522,7 +538,7 @@ Error Composer::setClientTarget(Display display, uint32_t slot, .height = target->getHeight(), .stride = target->getStride(), .layerCount = target->getLayerCount(), - .format = static_cast(target->getPixelFormat()), + .format = static_cast(target->getPixelFormat()), .usage = target->getUsage(), }; mWriter.setClientTargetMetadata(metadata); @@ -645,7 +661,7 @@ Error Composer::setLayerBuffer(Display display, Layer layer, .height = buffer->getHeight(), .stride = buffer->getStride(), .layerCount = buffer->getLayerCount(), - .format = static_cast(buffer->getPixelFormat()), + .format = static_cast(buffer->getPixelFormat()), .usage = buffer->getUsage(), }; mWriter.setLayerBufferMetadata(metadata); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index c0373aa6c1..98f2f9d387 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -39,10 +40,10 @@ using android::frameworks::vr::composer::V1_0::IVrComposerClient; using android::hardware::graphics::common::V1_0::ColorMode; using android::hardware::graphics::common::V1_0::ColorTransform; -using android::hardware::graphics::common::V1_0::Dataspace; using android::hardware::graphics::common::V1_0::Hdr; -using android::hardware::graphics::common::V1_0::PixelFormat; using android::hardware::graphics::common::V1_0::Transform; +using android::hardware::graphics::common::V1_1::Dataspace; +using android::hardware::graphics::common::V1_1::PixelFormat; using android::hardware::graphics::composer::V2_1::Config; using android::hardware::graphics::composer::V2_1::Display; diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 9398bdec92..e6d783434a 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -44,6 +44,8 @@ namespace android { // ---------------------------------------------------------------------------- +using ui::Dataspace; + /* * This implements the (main) framebuffer management. This class is used * mostly by SurfaceFlinger, but also by command line GL application. @@ -92,7 +94,7 @@ status_t FramebufferSurface::advanceFrame() { uint32_t slot = 0; sp buf; sp acquireFence(Fence::NO_FENCE); - android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN; + Dataspace dataspace = Dataspace::UNKNOWN; status_t result = nextBuffer(slot, buf, acquireFence, dataspace); mDataSpace = dataspace; if (result != NO_ERROR) { @@ -104,7 +106,7 @@ status_t FramebufferSurface::advanceFrame() { status_t FramebufferSurface::nextBuffer(uint32_t& outSlot, sp& outBuffer, sp& outFence, - android_dataspace_t& outDataspace) { + Dataspace& outDataspace) { Mutex::Autolock lock(mMutex); BufferItem item; @@ -139,7 +141,7 @@ status_t FramebufferSurface::nextBuffer(uint32_t& outSlot, outFence = item.mFence; mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer, &outSlot, &outBuffer); - outDataspace = item.mDataSpace; + outDataspace = static_cast(item.mDataSpace); status_t result = mHwc.setClientTarget(mDisplayType, outSlot, outFence, outBuffer, outDataspace); if (result != NO_ERROR) { @@ -178,7 +180,8 @@ void FramebufferSurface::onFrameCommitted() { void FramebufferSurface::dumpAsString(String8& result) const { Mutex::Autolock lock(mMutex); result.appendFormat(" FramebufferSurface: dataspace: %s(%d)\n", - dataspaceDetails(mDataSpace).c_str(), mDataSpace); + dataspaceDetails(static_cast(mDataSpace)).c_str(), + mDataSpace); ConsumerBase::dumpLocked(result, " "); } diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index ed756c49a1..0fd8e9eaa4 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -61,7 +61,7 @@ private: // BufferQueue and releases the previously latched buffer to the // BufferQueue. The new buffer is returned in the 'buffer' argument. status_t nextBuffer(uint32_t& outSlot, sp& outBuffer, - sp& outFence, android_dataspace_t& outDataspace); + sp& outFence, ui::Dataspace& outDataspace); // mDisplayType must match one of the HWC display types int mDisplayType; @@ -76,7 +76,7 @@ private: // compositing. Otherwise it will display the dataspace of the buffer // use for compositing which can change as wide-color content is // on/off. - android_dataspace mDataSpace; + ui::Dataspace mDataSpace; // mCurrentBuffer is the current buffer or nullptr to indicate that there is // no current buffer. diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index c2425cee74..2686788ade 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -47,6 +47,9 @@ using android::hardware::Void; namespace HWC2 { namespace Hwc2 = android::Hwc2; +using android::ui::ColorMode; +using android::ui::Dataspace; +using android::ui::PixelFormat; namespace { @@ -114,14 +117,13 @@ uint32_t Device::getMaxVirtualDisplayCount() const } Error Device::createVirtualDisplay(uint32_t width, uint32_t height, - android_pixel_format_t* format, Display** outDisplay) + PixelFormat* format, Display** outDisplay) { ALOGI("Creating virtual display"); hwc2_display_t displayId = 0; - auto intFormat = static_cast(*format); auto intError = mComposer->createVirtualDisplay(width, height, - &intFormat, &displayId); + format, &displayId); auto error = static_cast(intError); if (error != Error::None) { return error; @@ -131,7 +133,6 @@ Error Device::createVirtualDisplay(uint32_t width, uint32_t height, *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual); display->setConnected(true); *outDisplay = display.get(); - *format = static_cast(intFormat); mDisplays.emplace(displayId, std::move(display)); ALOGI("Created virtual display"); return Error::None; @@ -362,7 +363,7 @@ Error Display::getChangedCompositionTypes( return Error::None; } -Error Display::getColorModes(std::vector* outModes) const +Error Display::getColorModes(std::vector* outModes) const { auto intError = mComposer.getColorModes(mId, outModes); return static_cast(intError); @@ -516,17 +517,16 @@ Error Display::setActiveConfig(const std::shared_ptr& config) } Error Display::setClientTarget(uint32_t slot, const sp& target, - const sp& acquireFence, android_dataspace_t dataspace) + const sp& acquireFence, Dataspace dataspace) { // TODO: Properly encode client target surface damage int32_t fenceFd = acquireFence->dup(); auto intError = mComposer.setClientTarget(mId, slot, target, - fenceFd, static_cast(dataspace), - std::vector()); + fenceFd, dataspace, std::vector()); return static_cast(intError); } -Error Display::setColorMode(android::ui::ColorMode mode) +Error Display::setColorMode(ColorMode mode) { auto intError = mComposer.setColorMode(mId, mode); return static_cast(intError); @@ -765,14 +765,13 @@ Error Layer::setCompositionType(Composition type) return static_cast(intError); } -Error Layer::setDataspace(android_dataspace_t dataspace) +Error Layer::setDataspace(Dataspace dataspace) { if (dataspace == mDataSpace) { return Error::None; } mDataSpace = dataspace; - auto intDataspace = static_cast(dataspace); - auto intError = mComposer.setLayerDataspace(mDisplayId, mId, intDataspace); + auto intError = mComposer.setLayerDataspace(mDisplayId, mId, mDataSpace); return static_cast(intError); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 71c094a035..9b870e3ed9 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -96,7 +96,7 @@ public: uint32_t getMaxVirtualDisplayCount() const; Error createVirtualDisplay(uint32_t width, uint32_t height, - android_pixel_format_t* format, Display** outDisplay); + android::ui::PixelFormat* format, Display** outDisplay); void destroyDisplay(hwc2_display_t displayId); void onHotplug(hwc2_display_t displayId, Connection connection); @@ -234,7 +234,7 @@ public: [[clang::warn_unused_result]] Error setClientTarget( uint32_t slot, const android::sp& target, const android::sp& acquireFence, - android_dataspace_t dataspace); + android::ui::Dataspace dataspace); [[clang::warn_unused_result]] Error setColorMode( android::ui::ColorMode mode); [[clang::warn_unused_result]] Error setColorTransform( @@ -311,7 +311,7 @@ public: [[clang::warn_unused_result]] Error setColor(hwc_color_t color); [[clang::warn_unused_result]] Error setCompositionType(Composition type); [[clang::warn_unused_result]] Error setDataspace( - android_dataspace_t dataspace); + android::ui::Dataspace dataspace); [[clang::warn_unused_result]] Error setHdrMetadata(const android::HdrMetadata& metadata); [[clang::warn_unused_result]] Error setDisplayFrame( const android::Rect& frame); @@ -335,7 +335,7 @@ private: hwc2_display_t mDisplayId; hwc2_layer_t mId; - android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN; + android::ui::Dataspace mDataSpace = android::ui::Dataspace::UNKNOWN; android::HdrMetadata mHdrMetadata; std::function mLayerDestroyedListener; }; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 6bf2ee9362..29e2727b3e 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -179,7 +179,7 @@ bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp, } status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, - android_pixel_format_t* format, int32_t *outId) { + ui::PixelFormat* format, int32_t *outId) { if (mRemainingHwcVirtualDisplays == 0) { ALOGE("allocateVirtualDisplay: No remaining virtual displays"); return NO_MEMORY; @@ -387,7 +387,7 @@ void HWComposer::setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled) { status_t HWComposer::setClientTarget(int32_t displayId, uint32_t slot, const sp& acquireFence, const sp& target, - android_dataspace_t dataspace) { + ui::Dataspace dataspace) { if (!isValidDisplay(displayId)) { return BAD_INDEX; } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 0366a0d164..6e2e156abd 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -80,7 +80,7 @@ public: // Attempts to allocate a virtual display. If the virtual display is created // on the HWC device, outId will contain its HWC ID. status_t allocateVirtualDisplay(uint32_t width, uint32_t height, - android_pixel_format_t* format, int32_t* outId); + ui::PixelFormat* format, int32_t* outId); // Attempts to create a new layer on this display HWC2::Layer* createLayer(int32_t displayId); @@ -92,7 +92,7 @@ public: status_t setClientTarget(int32_t displayId, uint32_t slot, const sp& acquireFence, - const sp& target, android_dataspace_t dataspace); + const sp& target, ui::Dataspace dataspace); // Present layers to the display and read releaseFences. status_t presentAndGetReleaseFences(int32_t displayId); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 3480b24390..9a2817dba1 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -222,7 +222,7 @@ status_t VirtualDisplaySurface::advanceFrame() { // TODO: Correctly propagate the dataspace from GL composition result = mHwc.setClientTarget(mDisplayId, hwcSlot, mFbFence, - hwcBuffer, HAL_DATASPACE_UNKNOWN); + hwcBuffer, ui::Dataspace::UNKNOWN); } return result; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5c945edb5f..9d356d86c7 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -122,7 +122,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mCurrentState.layerStack = 0; mCurrentState.sequence = 0; mCurrentState.requested = mCurrentState.active; - mCurrentState.dataSpace = HAL_DATASPACE_UNKNOWN; + mCurrentState.dataSpace = ui::Dataspace::UNKNOWN; mCurrentState.appId = 0; mCurrentState.type = 0; @@ -1327,7 +1327,7 @@ bool Layer::setLayerStack(uint32_t layerStack) { return true; } -bool Layer::setDataSpace(android_dataspace dataSpace) { +bool Layer::setDataSpace(ui::Dataspace dataSpace) { if (mCurrentState.dataSpace == dataSpace) return false; mCurrentState.sequence++; mCurrentState.dataSpace = dataSpace; @@ -1336,7 +1336,7 @@ bool Layer::setDataSpace(android_dataspace dataSpace) { return true; } -android_dataspace Layer::getDataSpace() const { +ui::Dataspace Layer::getDataSpace() const { return mCurrentState.dataSpace; } @@ -1432,7 +1432,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); - info.mDataSpace = getDataSpace(); + info.mDataSpace = static_cast(getDataSpace()); info.mMatrix[0][0] = ds.active.transform[0][0]; info.mMatrix[0][1] = ds.active.transform[0][1]; info.mMatrix[1][0] = ds.active.transform[1][0]; @@ -1895,7 +1895,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_is_opaque(isOpaque(state)); layerInfo->set_invalidate(contentDirty); - layerInfo->set_dataspace(dataspaceDetails(getDataSpace())); + layerInfo->set_dataspace(dataspaceDetails(static_cast(getDataSpace()))); layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat())); LayerProtoHelper::writeToProto(getColor(), layerInfo->mutable_color()); LayerProtoHelper::writeToProto(state.color, layerInfo->mutable_requested_color()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 69ffb2018c..8d2a0488dc 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -207,7 +207,7 @@ public: // dependent. Region activeTransparentRegion; Region requestedTransparentRegion; - android_dataspace dataSpace; + ui::Dataspace dataSpace; int32_t appId; int32_t type; @@ -285,8 +285,8 @@ public: bool setTransparentRegionHint(const Region& transparent); bool setFlags(uint8_t flags, uint8_t mask); bool setLayerStack(uint32_t layerStack); - bool setDataSpace(android_dataspace dataSpace); - android_dataspace getDataSpace() const; + bool setDataSpace(ui::Dataspace dataSpace); + ui::Dataspace getDataSpace() const; uint32_t getLayerStack() const; void deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber); void deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber); diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index ea7dc2f1fd..1eda900f47 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -109,6 +109,8 @@ namespace RE { namespace impl { // --------------------------------------------------------------------------- +using ui::Dataspace; + GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) : mVpWidth(0), mVpHeight(0), mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) { glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); @@ -214,11 +216,11 @@ void GLES20RenderEngine::setSourceY410BT2020(bool enable) { mState.setY410BT2020(enable); } -void GLES20RenderEngine::setSourceDataSpace(android_dataspace source) { +void GLES20RenderEngine::setSourceDataSpace(Dataspace source) { mDataSpace = source; } -void GLES20RenderEngine::setOutputDataSpace(android_dataspace dataspace) { +void GLES20RenderEngine::setOutputDataSpace(Dataspace dataspace) { mOutputDataSpace = dataspace; } @@ -301,14 +303,14 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { mesh.getByteStride(), mesh.getPositions()); // DISPLAY_P3 is the only supported wide color output - if (mPlatformHasWideColor && mOutputDataSpace == HAL_DATASPACE_DISPLAY_P3) { + if (mPlatformHasWideColor && mOutputDataSpace == Dataspace::DISPLAY_P3) { Description wideColorState = mState; - switch (int(mDataSpace)) { - case HAL_DATASPACE_DISPLAY_P3: + switch (mDataSpace) { + case Dataspace::DISPLAY_P3: // input matches output break; - case HAL_DATASPACE_BT2020_PQ: - case HAL_DATASPACE_BT2020_ITU_PQ: + case Dataspace::BT2020_PQ: + case Dataspace::BT2020_ITU_PQ: wideColorState.setColorMatrix(mState.getColorMatrix() * mBt2020ToDisplayP3); wideColorState.setInputTransferFunction(Description::TransferFunction::ST2084); wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB); @@ -317,7 +319,7 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { default: // treat all other dataspaces as sRGB wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3); - if ((mDataSpace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_LINEAR) { + if ((mDataSpace & Dataspace::TRANSFER_MASK) & Dataspace::TRANSFER_LINEAR) { wideColorState.setInputTransferFunction(Description::TransferFunction::LINEAR); } else { wideColorState.setInputTransferFunction(Description::TransferFunction::SRGB); @@ -350,8 +352,8 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { void GLES20RenderEngine::dump(String8& result) { RenderEngine::dump(result); result.appendFormat("RenderEngine last dataspace conversion: (%s) to (%s)\n", - dataspaceDetails(mDataSpace).c_str(), - dataspaceDetails(mOutputDataSpace).c_str()); + dataspaceDetails(static_cast(mDataSpace)).c_str(), + dataspaceDetails(static_cast(mOutputDataSpace)).c_str()); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index db3f79281e..99da19d6b1 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -73,14 +73,14 @@ protected: // Color management related functions and state void setSourceY410BT2020(bool enable) override; - void setSourceDataSpace(android_dataspace source) override; - void setOutputDataSpace(android_dataspace dataspace) override; + void setSourceDataSpace(ui::Dataspace source) override; + void setOutputDataSpace(ui::Dataspace dataspace) override; // Current dataspace of layer being rendered - android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN; + ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN; // Current output dataspace of the render engine - android_dataspace mOutputDataSpace = HAL_DATASPACE_UNKNOWN; + ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN; // Currently only supporting sRGB, BT2020 and DisplayP3 color spaces const bool mPlatformHasWideColor = false; diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index d1405740e6..f78b230778 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -119,8 +119,8 @@ public: // wide color support virtual void setSourceY410BT2020(bool enable) = 0; - virtual void setSourceDataSpace(android_dataspace source) = 0; - virtual void setOutputDataSpace(android_dataspace dataspace) = 0; + virtual void setSourceDataSpace(ui::Dataspace source) = 0; + virtual void setOutputDataSpace(ui::Dataspace dataspace) = 0; // drawing virtual void drawMesh(const Mesh& mesh) = 0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f7f5b58616..ea759588df 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -105,6 +105,7 @@ namespace android { using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; using ui::ColorMode; +using ui::Dataspace; namespace { class ConditionalLock { @@ -1837,7 +1838,7 @@ mat4 SurfaceFlinger::computeSaturationMatrix() const { // pickColorMode translates a given dataspace into the best available color mode. // Currently only support sRGB and Display-P3. -ColorMode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const { +ColorMode SurfaceFlinger::pickColorMode(Dataspace dataSpace) const { if (mForceNativeColorMode) { return ColorMode::NATIVE; } @@ -1845,47 +1846,48 @@ ColorMode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const { switch (dataSpace) { // treat Unknown as regular SRGB buffer, since that's what the rest of the // system expects. - case HAL_DATASPACE_UNKNOWN: - case HAL_DATASPACE_SRGB: - case HAL_DATASPACE_V0_SRGB: + case Dataspace::UNKNOWN: + case Dataspace::SRGB: + case Dataspace::V0_SRGB: return ColorMode::SRGB; break; - case HAL_DATASPACE_DISPLAY_P3: + case Dataspace::DISPLAY_P3: return ColorMode::DISPLAY_P3; break; default: // TODO (courtneygo): Do we want to assert an error here? - ALOGE("No color mode mapping for %s (%#x)", dataspaceDetails(dataSpace).c_str(), + ALOGE("No color mode mapping for %s (%#x)", + dataspaceDetails(static_cast(dataSpace)).c_str(), dataSpace); return ColorMode::SRGB; break; } } -android_dataspace SurfaceFlinger::bestTargetDataSpace( - android_dataspace a, android_dataspace b, bool hasHdr) const { +Dataspace SurfaceFlinger::bestTargetDataSpace( + Dataspace a, Dataspace b, bool hasHdr) const { // Only support sRGB and Display-P3 right now. - if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) { - return HAL_DATASPACE_DISPLAY_P3; + if (a == Dataspace::DISPLAY_P3 || b == Dataspace::DISPLAY_P3) { + return Dataspace::DISPLAY_P3; } - if (a == HAL_DATASPACE_V0_SCRGB_LINEAR || b == HAL_DATASPACE_V0_SCRGB_LINEAR) { - return HAL_DATASPACE_DISPLAY_P3; + if (a == Dataspace::V0_SCRGB_LINEAR || b == Dataspace::V0_SCRGB_LINEAR) { + return Dataspace::DISPLAY_P3; } - if (a == HAL_DATASPACE_V0_SCRGB || b == HAL_DATASPACE_V0_SCRGB) { - return HAL_DATASPACE_DISPLAY_P3; + if (a == Dataspace::V0_SCRGB || b == Dataspace::V0_SCRGB) { + return Dataspace::DISPLAY_P3; } if (!hasHdr) { - if (a == HAL_DATASPACE_BT2020_PQ || b == HAL_DATASPACE_BT2020_PQ) { - return HAL_DATASPACE_DISPLAY_P3; + if (a == Dataspace::BT2020_PQ || b == Dataspace::BT2020_PQ) { + return Dataspace::DISPLAY_P3; } - if (a == HAL_DATASPACE_BT2020_ITU_PQ || b == HAL_DATASPACE_BT2020_ITU_PQ) { - return HAL_DATASPACE_DISPLAY_P3; + if (a == Dataspace::BT2020_ITU_PQ || b == Dataspace::BT2020_ITU_PQ) { + return Dataspace::DISPLAY_P3; } } - return HAL_DATASPACE_V0_SRGB; + return Dataspace::V0_SRGB; } void SurfaceFlinger::setUpHWComposer() { @@ -1966,8 +1968,8 @@ void SurfaceFlinger::setUpHWComposer() { "display %zd: %d", displayId, result); } for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ || - layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) && + if ((layer->getDataSpace() == Dataspace::BT2020_PQ || + layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && !displayDevice->getHdrSupport()) { layer->forceClientComposition(hwcId); } @@ -1983,14 +1985,14 @@ void SurfaceFlinger::setUpHWComposer() { if (hasWideColorDisplay) { ColorMode newColorMode; - android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB; + Dataspace newDataSpace = Dataspace::V0_SRGB; for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace, displayDevice->getHdrSupport()); ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)", - layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(), - layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace); + layer->getName().string(), dataspaceDetails(static_cast(layer->getDataSpace())).c_str(), + layer->getDataSpace(), dataspaceDetails(static_cast(newDataSpace)).c_str(), newDataSpace); } newColorMode = pickColorMode(newDataSpace); @@ -2268,7 +2270,7 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( defaultColorMode = ColorMode::SRGB; } setActiveColorModeInternal(hw, defaultColorMode); - hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN); + hw->setCompositionDataSpace(Dataspace::UNKNOWN); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); hw->setDisplayName(state.displayName); @@ -2371,7 +2373,7 @@ void SurfaceFlinger::processDisplayChangesLocked() { int intFormat = 0; status = state.surface->query(NATIVE_WINDOW_FORMAT, &intFormat); ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status); - auto format = static_cast(intFormat); + auto format = static_cast(intFormat); getBE().mHwc->allocateVirtualDisplay(width, height, &format, &hwcId); } @@ -2832,10 +2834,10 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev if (hasClientComposition) { ALOGV("hasClientComposition"); - android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN; + Dataspace outputDataspace = Dataspace::UNKNOWN; if (displayDevice->getWideColorSupport() && displayDevice->getActiveColorMode() == ColorMode::DISPLAY_P3) { - outputDataspace = HAL_DATASPACE_DISPLAY_P3; + outputDataspace = Dataspace::DISPLAY_P3; } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); @@ -4802,10 +4804,10 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight); } - android_dataspace outputDataspace = HAL_DATASPACE_UNKNOWN; + Dataspace outputDataspace = Dataspace::UNKNOWN; if (renderArea.getWideColorSupport() && renderArea.getActiveColorMode() == ColorMode::DISPLAY_P3) { - outputDataspace = HAL_DATASPACE_DISPLAY_P3; + outputDataspace = Dataspace::DISPLAY_P3; } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c7c308883b..23c9684227 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -636,8 +636,8 @@ private: // Given a dataSpace, returns the appropriate color_mode to use // to display that dataSpace. - ui::ColorMode pickColorMode(android_dataspace dataSpace) const; - android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b, + ui::ColorMode pickColorMode(ui::Dataspace dataSpace) const; + ui::Dataspace bestTargetDataSpace(ui::Dataspace a, ui::Dataspace b, bool hasHdr) const; mat4 computeSaturationMatrix() const; diff --git a/services/surfaceflinger/tests/hwc2/Android.bp b/services/surfaceflinger/tests/hwc2/Android.bp index e980522702..6c0e4abcfe 100644 --- a/services/surfaceflinger/tests/hwc2/Android.bp +++ b/services/surfaceflinger/tests/hwc2/Android.bp @@ -42,6 +42,7 @@ cc_test { ], shared_libs: [ "android.hardware.graphics.common@1.0", + "android.hardware.graphics.common@1.1", "libcutils", "libEGL", "libGLESv2", diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index b3f1b69f71..13774b4ed3 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -36,6 +36,7 @@ #include "Hwc2TestVirtualDisplay.h" using android::ui::ColorMode; +using android::ui::Dataspace; void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); @@ -442,14 +443,14 @@ public: } void setLayerDataspace(hwc2_display_t display, hwc2_layer_t layer, - android_dataspace_t dataspace, hwc2_error_t* outErr = nullptr) + Dataspace dataspace, hwc2_error_t* outErr = nullptr) { auto pfn = reinterpret_cast( getFunction(HWC2_FUNCTION_SET_LAYER_DATASPACE)); ASSERT_TRUE(pfn) << "failed to get function"; auto err = static_cast(pfn(mHwc2Device, display, - layer, dataspace)); + layer, static_cast(dataspace))); if (outErr) { *outErr = err; } else { @@ -790,14 +791,14 @@ public: void getClientTargetSupport(hwc2_display_t display, int32_t width, int32_t height, android_pixel_format_t format, - android_dataspace_t dataspace, hwc2_error_t* outErr = nullptr) + Dataspace dataspace, hwc2_error_t* outErr = nullptr) { auto pfn = reinterpret_cast( getFunction(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT)); ASSERT_TRUE(pfn) << "failed to get function"; auto err = static_cast(pfn(mHwc2Device, display, width, - height, format, dataspace)); + height, format, static_cast(dataspace))); if (outErr) { *outErr = err; } else { @@ -807,7 +808,7 @@ public: } void setClientTarget(hwc2_display_t display, buffer_handle_t handle, - int32_t acquireFence, android_dataspace_t dataspace, + int32_t acquireFence, Dataspace dataspace, hwc_region_t damage, hwc2_error_t* outErr = nullptr) { auto pfn = reinterpret_cast( @@ -815,7 +816,7 @@ public: ASSERT_TRUE(pfn) << "failed to get function"; auto err = static_cast(pfn(mHwc2Device, display, handle, - acquireFence, dataspace, damage)); + acquireFence, static_cast(dataspace), damage)); if (outErr) { *outErr = err; } else { @@ -1691,7 +1692,7 @@ protected: const std::set& clearLayers, bool flipClientTarget, const Area& displayArea) { - android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN; + Dataspace dataspace = Dataspace::UNKNOWN; hwc_region_t damage = { }; buffer_handle_t handle; int32_t acquireFence; @@ -3716,7 +3717,7 @@ TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_unsupported) * layer. */ TEST_F(Hwc2Test, SET_CLIENT_TARGET_basic) { - const android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN; + const Dataspace dataspace = Dataspace::UNKNOWN; const hwc_region_t damage = { }; const size_t layerCnt = 1; @@ -3795,7 +3796,7 @@ TEST_F(Hwc2Test, SET_CLIENT_TARGET_bad_display) std::set clientLayers; std::set flipClientTargetLayers; bool flipClientTarget = true; - const android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN; + const Dataspace dataspace = Dataspace::UNKNOWN; const hwc_region_t damage = { }; buffer_handle_t handle; int32_t acquireFence; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp index 69254921d4..14c60a7d26 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp @@ -91,7 +91,7 @@ Area Hwc2TestClientTargetSupport::getBufferArea() const return mBufferArea.get(); } -android_dataspace_t Hwc2TestClientTargetSupport::getDataspace() const +android::ui::Dataspace Hwc2TestClientTargetSupport::getDataspace() const { return mDataspace.get(); } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h index 3b47978bef..6f4090f321 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h @@ -53,7 +53,7 @@ public: bool advance(); Area getBufferArea() const; - android_dataspace_t getDataspace() const; + android::ui::Dataspace getDataspace() const; const hwc_region_t getSurfaceDamage() const; private: diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index 937fce28fb..c1c9cc8f5b 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -146,7 +146,7 @@ hwc_rect_t Hwc2TestLayer::getCursorPosition() const return mDisplayFrame.get(); } -android_dataspace_t Hwc2TestLayer::getDataspace() const +android::ui::Dataspace Hwc2TestLayer::getDataspace() const { return mDataspace.get(); } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index 0e7dd228fb..29ae521804 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -54,7 +54,7 @@ public: hwc_color_t getColor() const; hwc2_composition_t getComposition() const; hwc_rect_t getCursorPosition() const; - android_dataspace_t getDataspace() const; + android::ui::Dataspace getDataspace() const; hwc_rect_t getDisplayFrame() const; float getPlaneAlpha() const; hwc_frect_t getSourceCrop() const; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp index 495ef79609..90127a1302 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp @@ -169,7 +169,7 @@ hwc_rect_t Hwc2TestLayers::getCursorPosition(hwc2_layer_t layer) const return mTestLayers.at(layer).getCursorPosition(); } -android_dataspace_t Hwc2TestLayers::getDataspace(hwc2_layer_t layer) const +android::ui::Dataspace Hwc2TestLayers::getDataspace(hwc2_layer_t layer) const { if (mTestLayers.count(layer) == 0) { []() { GTEST_FAIL(); }(); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h index d95a91f485..909dd486e8 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h @@ -63,7 +63,7 @@ public: hwc_color_t getColor(hwc2_layer_t layer) const; hwc2_composition_t getComposition(hwc2_layer_t layer) const; hwc_rect_t getCursorPosition(hwc2_layer_t layer) const; - android_dataspace_t getDataspace(hwc2_layer_t layer) const; + android::ui::Dataspace getDataspace(hwc2_layer_t layer) const; hwc_rect_t getDisplayFrame(hwc2_layer_t layer) const; android_pixel_format_t getFormat(hwc2_layer_t layer) const; float getPlaneAlpha(hwc2_layer_t layer) const; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index 5b3bbeb708..c5b92d0664 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -262,62 +262,62 @@ Hwc2TestDataspace::Hwc2TestDataspace(Hwc2TestCoverage coverage) std::string Hwc2TestDataspace::dump() const { std::stringstream dmp; - dmp << "\tdataspace: " << get() << "\n"; + dmp << "\tdataspace: " << static_cast(get()) << "\n"; return dmp.str(); } -const std::vector Hwc2TestDataspace::defaultDataspaces = { - HAL_DATASPACE_UNKNOWN, -}; - -const std::vector Hwc2TestDataspace::basicDataspaces = { - HAL_DATASPACE_UNKNOWN, - HAL_DATASPACE_V0_SRGB, -}; - -const std::vector Hwc2TestDataspace::completeDataspaces = { - HAL_DATASPACE_UNKNOWN, - HAL_DATASPACE_ARBITRARY, - HAL_DATASPACE_STANDARD_SHIFT, - HAL_DATASPACE_STANDARD_MASK, - HAL_DATASPACE_STANDARD_UNSPECIFIED, - HAL_DATASPACE_STANDARD_BT709, - HAL_DATASPACE_STANDARD_BT601_625, - HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED, - HAL_DATASPACE_STANDARD_BT601_525, - HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED, - HAL_DATASPACE_STANDARD_BT2020, - HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE, - HAL_DATASPACE_STANDARD_BT470M, - HAL_DATASPACE_STANDARD_FILM, - HAL_DATASPACE_TRANSFER_SHIFT, - HAL_DATASPACE_TRANSFER_MASK, - HAL_DATASPACE_TRANSFER_UNSPECIFIED, - HAL_DATASPACE_TRANSFER_LINEAR, - HAL_DATASPACE_TRANSFER_SRGB, - HAL_DATASPACE_TRANSFER_SMPTE_170M, - HAL_DATASPACE_TRANSFER_GAMMA2_2, - HAL_DATASPACE_TRANSFER_GAMMA2_8, - HAL_DATASPACE_TRANSFER_ST2084, - HAL_DATASPACE_TRANSFER_HLG, - HAL_DATASPACE_RANGE_SHIFT, - HAL_DATASPACE_RANGE_MASK, - HAL_DATASPACE_RANGE_UNSPECIFIED, - HAL_DATASPACE_RANGE_FULL, - HAL_DATASPACE_RANGE_LIMITED, - HAL_DATASPACE_SRGB_LINEAR, - HAL_DATASPACE_V0_SRGB_LINEAR, - HAL_DATASPACE_SRGB, - HAL_DATASPACE_V0_SRGB, - HAL_DATASPACE_JFIF, - HAL_DATASPACE_V0_JFIF, - HAL_DATASPACE_BT601_625, - HAL_DATASPACE_V0_BT601_625, - HAL_DATASPACE_BT601_525, - HAL_DATASPACE_V0_BT601_525, - HAL_DATASPACE_BT709, - HAL_DATASPACE_V0_BT709, - HAL_DATASPACE_DEPTH, +const std::vector Hwc2TestDataspace::defaultDataspaces = { + android::ui::Dataspace::UNKNOWN, +}; + +const std::vector Hwc2TestDataspace::basicDataspaces = { + android::ui::Dataspace::UNKNOWN, + android::ui::Dataspace::V0_SRGB, +}; + +const std::vector Hwc2TestDataspace::completeDataspaces = { + android::ui::Dataspace::UNKNOWN, + android::ui::Dataspace::ARBITRARY, + android::ui::Dataspace::STANDARD_SHIFT, + android::ui::Dataspace::STANDARD_MASK, + android::ui::Dataspace::STANDARD_UNSPECIFIED, + android::ui::Dataspace::STANDARD_BT709, + android::ui::Dataspace::STANDARD_BT601_625, + android::ui::Dataspace::STANDARD_BT601_625_UNADJUSTED, + android::ui::Dataspace::STANDARD_BT601_525, + android::ui::Dataspace::STANDARD_BT601_525_UNADJUSTED, + android::ui::Dataspace::STANDARD_BT2020, + android::ui::Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE, + android::ui::Dataspace::STANDARD_BT470M, + android::ui::Dataspace::STANDARD_FILM, + android::ui::Dataspace::TRANSFER_SHIFT, + android::ui::Dataspace::TRANSFER_MASK, + android::ui::Dataspace::TRANSFER_UNSPECIFIED, + android::ui::Dataspace::TRANSFER_LINEAR, + android::ui::Dataspace::TRANSFER_SRGB, + android::ui::Dataspace::TRANSFER_SMPTE_170M, + android::ui::Dataspace::TRANSFER_GAMMA2_2, + android::ui::Dataspace::TRANSFER_GAMMA2_8, + android::ui::Dataspace::TRANSFER_ST2084, + android::ui::Dataspace::TRANSFER_HLG, + android::ui::Dataspace::RANGE_SHIFT, + android::ui::Dataspace::RANGE_MASK, + android::ui::Dataspace::RANGE_UNSPECIFIED, + android::ui::Dataspace::RANGE_FULL, + android::ui::Dataspace::RANGE_LIMITED, + android::ui::Dataspace::SRGB_LINEAR, + android::ui::Dataspace::V0_SRGB_LINEAR, + android::ui::Dataspace::SRGB, + android::ui::Dataspace::V0_SRGB, + android::ui::Dataspace::JFIF, + android::ui::Dataspace::V0_JFIF, + android::ui::Dataspace::BT601_625, + android::ui::Dataspace::V0_BT601_625, + android::ui::Dataspace::BT601_525, + android::ui::Dataspace::V0_BT601_525, + android::ui::Dataspace::BT709, + android::ui::Dataspace::V0_BT709, + android::ui::Dataspace::DEPTH, }; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index cb811e06e2..d7082f3cb5 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -20,6 +20,7 @@ #include #include +#include #include #define HWC2_INCLUDE_STRINGIFICATION @@ -229,16 +230,16 @@ protected: }; -class Hwc2TestDataspace : public Hwc2TestProperty { +class Hwc2TestDataspace : public Hwc2TestProperty { public: Hwc2TestDataspace(Hwc2TestCoverage coverage); std::string dump() const override; protected: - static const std::vector defaultDataspaces; - static const std::vector basicDataspaces; - static const std::vector completeDataspaces; + static const std::vector defaultDataspaces; + static const std::vector basicDataspaces; + static const std::vector completeDataspaces; static const std::array mCompositionSupport; }; diff --git a/services/surfaceflinger/tests/unittests/MockComposer.h b/services/surfaceflinger/tests/unittests/MockComposer.h index acd9b3099a..00e565b75c 100644 --- a/services/surfaceflinger/tests/unittests/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/MockComposer.h @@ -29,10 +29,10 @@ namespace mock { using android::hardware::graphics::common::V1_0::ColorMode; using android::hardware::graphics::common::V1_0::ColorTransform; -using android::hardware::graphics::common::V1_0::Dataspace; using android::hardware::graphics::common::V1_0::Hdr; -using android::hardware::graphics::common::V1_0::PixelFormat; using android::hardware::graphics::common::V1_0::Transform; +using android::hardware::graphics::common::V1_1::Dataspace; +using android::hardware::graphics::common::V1_1::PixelFormat; using android::hardware::graphics::composer::V2_1::Config; using android::hardware::graphics::composer::V2_1::Display; diff --git a/services/surfaceflinger/tests/unittests/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/MockRenderEngine.h index 6d3e17ff73..9bb2a3c961 100644 --- a/services/surfaceflinger/tests/unittests/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/MockRenderEngine.h @@ -64,8 +64,8 @@ public: MOCK_METHOD0(disableTexturing, void()); MOCK_METHOD0(disableBlending, void()); MOCK_METHOD1(setSourceY410BT2020, void(bool)); - MOCK_METHOD1(setSourceDataSpace, void(android_dataspace)); - MOCK_METHOD1(setOutputDataSpace, void(android_dataspace)); + MOCK_METHOD1(setSourceDataSpace, void(ui::Dataspace)); + MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace)); MOCK_METHOD2(bindNativeBufferAsFrameBuffer, void(ANativeWindowBuffer*, RE::BindNativeBufferAsFramebuffer*)); MOCK_METHOD1(unbindNativeBufferAsFrameBuffer, void(RE::BindNativeBufferAsFramebuffer*)); -- cgit v1.2.3-59-g8ed1b From a9dcf11831380f2b9f310ceb9a72f2bf953d25e1 Mon Sep 17 00:00:00 2001 From: Jeffrey Kardatzke Date: Tue, 3 Apr 2018 10:45:55 -0700 Subject: Update dirty regions when requested to repaint everything This is a merge from: ag/3827114 The issue was when an HWC implementation was requesting a composer refresh, it wouldn't actually mark the areas as dirty so the mustRecompose flag wasn't getting sent when a virtual display was doing the redraw. That then prevented the changes from its output buffer from propagating through to the consumer of that surface. Bug: 77335744 Bug: 77546473 Test: Manually verified refreshes propagate through Change-Id: Ia7a3dc15c96626a213c4459dac4f695d91540fb5 --- services/surfaceflinger/SurfaceFlinger.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f180a3b285..90743f2e10 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4458,6 +4458,11 @@ status_t SurfaceFlinger::onTransact( void SurfaceFlinger::repaintEverythingLocked() { android_atomic_or(1, &mRepaintEverything); + for (size_t dpy = 0; dpy < mDisplays.size(); dpy++) { + const sp& displayDevice(mDisplays[dpy]); + const Rect bounds(displayDevice->getBounds()); + displayDevice->dirtyRegion.orSelf(Region(bounds)); + } signalTransaction(); } -- cgit v1.2.3-59-g8ed1b From 0e7a791d51e92aafefd416044a2d38b6eec22a00 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Thu, 5 Apr 2018 14:36:36 -0700 Subject: [SurfaceFlinger] Plumb HAL to hardware composer. Previously we introduced HIDL interfaces for Auto Color support. This patch implements HAL interfaces in DisplayHardware/. BUG: 73824924 BUG: 73825729 Test: Build Change-Id: I4f2011bfa9306552d50a88fe0f065932be3efd0c --- libs/ui/DebugUtils.cpp | 24 +++ libs/ui/include/ui/DebugUtils.h | 1 + libs/ui/include/ui/GraphicTypes.h | 3 +- .../surfaceflinger/DisplayHardware/ComposerHal.cpp | 193 ++++++++++++++------- .../surfaceflinger/DisplayHardware/ComposerHal.h | 28 ++- services/surfaceflinger/DisplayHardware/HWC2.cpp | 18 +- services/surfaceflinger/DisplayHardware/HWC2.h | 8 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 49 +++++- .../surfaceflinger/DisplayHardware/HWComposer.h | 8 +- .../RenderEngine/GLES20RenderEngine.cpp | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 3 +- .../tests/unittests/DisplayTransactionTest.cpp | 2 +- .../surfaceflinger/tests/unittests/MockComposer.h | 7 +- 13 files changed, 261 insertions(+), 84 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp index 58fed84ea8..61df02d41d 100644 --- a/libs/ui/DebugUtils.cpp +++ b/libs/ui/DebugUtils.cpp @@ -23,6 +23,7 @@ using android::base::StringPrintf; using android::ui::ColorMode; +using android::ui::RenderIntent; std::string decodeStandard(android_dataspace dataspace) { const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK); @@ -229,6 +230,15 @@ std::string decodeColorMode(ColorMode colorMode) { case ColorMode::DISPLAY_P3: return std::string("ColorMode::DISPLAY_P3"); + + case ColorMode::BT2020: + return std::string("ColorMode::BT2020"); + + case ColorMode::BT2100_PQ: + return std::string("ColorMode::BT2100_PQ"); + + case ColorMode::BT2100_HLG: + return std::string("ColorMode::BT2100_HLG"); } return android::base::StringPrintf("Unknown color mode %d", colorMode); @@ -294,6 +304,20 @@ std::string decodePixelFormat(android::PixelFormat format) { } } +std::string decodeRenderIntent(RenderIntent renderIntent) { + switch(renderIntent) { + case RenderIntent::COLORIMETRIC: + return std::string("RenderIntent::COLORIMETRIC"); + case RenderIntent::ENHANCE: + return std::string("RenderIntent::ENHANCE"); + case RenderIntent::TONE_MAP_COLORIMETRIC: + return std::string("RenderIntent::TONE_MAP_COLORIMETRIC"); + case RenderIntent::TONE_MAP_ENHANCE: + return std::string("RenderIntent::TONE_MAP_ENHANCE"); + } + return std::string("Unknown RenderIntent"); +} + std::string to_string(const android::Rect& rect) { return StringPrintf("(%4d,%4d,%4d,%4d)", rect.left, rect.top, rect.right, rect.bottom); } diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h index 5e5df43740..92b2bfb282 100644 --- a/libs/ui/include/ui/DebugUtils.h +++ b/libs/ui/include/ui/DebugUtils.h @@ -32,4 +32,5 @@ std::string dataspaceDetails(android_dataspace dataspace); std::string decodeColorMode(android::ui::ColorMode colormode); std::string decodeColorTransform(android_color_transform colorTransform); std::string decodePixelFormat(android::PixelFormat format); +std::string decodeRenderIntent(android::ui::RenderIntent renderIntent); std::string to_string(const android::Rect& rect); diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h index 92a5519898..bd5722fdb0 100644 --- a/libs/ui/include/ui/GraphicTypes.h +++ b/libs/ui/include/ui/GraphicTypes.h @@ -24,9 +24,10 @@ namespace android { namespace ui { -using android::hardware::graphics::common::V1_0::ColorMode; +using android::hardware::graphics::common::V1_1::ColorMode; using android::hardware::graphics::common::V1_1::Dataspace; using android::hardware::graphics::common::V1_1::PixelFormat; +using android::hardware::graphics::common::V1_1::RenderIntent; } // namespace ui } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index bbffd0ae7f..5daa87ee35 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -350,15 +350,29 @@ Error Composer::getColorModes(Display display, std::vector* outModes) { Error error = kDefaultError; - mClient->getColorModes(display, - [&](const auto& tmpError, const auto& tmpModes) { - error = tmpError; - if (error != Error::NONE) { - return; - } - *outModes = tmpModes; - }); + if (mClient_2_2) { + mClient_2_2->getColorModes_2_2(display, + [&](const auto& tmpError, const auto& tmpModes) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outModes = tmpModes; + }); + } else { + mClient->getColorModes(display, + [&](const auto& tmpError, const auto& tmpModes) { + error = tmpError; + if (error != Error::NONE) { + return; + } + for (V1_0::ColorMode colorMode : tmpModes) { + outModes->push_back(static_cast(colorMode)); + } + }); + } return error; } @@ -479,25 +493,6 @@ Error Composer::getHdrCapabilities(Display display, return error; } -Error Composer::getPerFrameMetadataKeys( - Display display, std::vector* outKeys) { - if (!mClient_2_2) { - return Error::UNSUPPORTED; - } - - Error error = kDefaultError; - mClient_2_2->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) { - error = tmpError; - if (error != Error::NONE) { - return; - } - - *outKeys = tmpKeys; - }); - - return error; -} - Error Composer::getReleaseFences(Display display, std::vector* outLayers, std::vector* outReleaseFences) { @@ -553,9 +548,16 @@ Error Composer::setClientTarget(Display display, uint32_t slot, return Error::NONE; } -Error Composer::setColorMode(Display display, ColorMode mode) +Error Composer::setColorMode(Display display, ColorMode mode, + RenderIntent renderIntent) { - auto ret = mClient->setColorMode(display, mode); + hardware::Return ret(kDefaultError); + if (mClient_2_2) { + ret = mClient_2_2->setColorMode_2_2(display, mode, renderIntent); + } else { + ret = mClient->setColorMode(display, + static_cast(mode)); + } return unwrapRet(ret); } @@ -862,39 +864,44 @@ Error Composer::execute() } Error error = kDefaultError; - auto ret = mClient->executeCommands(commandLength, commandHandles, - [&](const auto& tmpError, const auto& tmpOutChanged, - const auto& tmpOutLength, const auto& tmpOutHandles) - { - error = tmpError; - - // set up new output command queue if necessary - if (error == Error::NONE && tmpOutChanged) { - error = kDefaultError; - mClient->getOutputCommandQueue( - [&](const auto& tmpError, - const auto& tmpDescriptor) - { - error = tmpError; - if (error != Error::NONE) { - return; - } - - mReader.setMQDescriptor(tmpDescriptor); - }); - } - - if (error != Error::NONE) { - return; - } - - if (mReader.readQueue(tmpOutLength, tmpOutHandles)) { - error = mReader.parse(); - mReader.reset(); - } else { - error = Error::NO_RESOURCES; - } - }); + hardware::Return ret; + auto hidl_callback = [&](const auto& tmpError, const auto& tmpOutChanged, + const auto& tmpOutLength, const auto& tmpOutHandles) + { + error = tmpError; + + // set up new output command queue if necessary + if (error == Error::NONE && tmpOutChanged) { + error = kDefaultError; + mClient->getOutputCommandQueue( + [&](const auto& tmpError, + const auto& tmpDescriptor) + { + error = tmpError; + if (error != Error::NONE) { + return; + } + + mReader.setMQDescriptor(tmpDescriptor); + }); + } + + if (error != Error::NONE) { + return; + } + + if (mReader.readQueue(tmpOutLength, tmpOutHandles)) { + error = mReader.parse(); + mReader.reset(); + } else { + error = Error::NO_RESOURCES; + } + }; + if (mClient_2_2) { + ret = mClient_2_2->executeCommands_2_2(commandLength, commandHandles, hidl_callback); + } else { + ret = mClient->executeCommands(commandLength, commandHandles, hidl_callback); + } // executeCommands can fail because of out-of-fd and we do not want to // abort() in that case if (!ret.isOk()) { @@ -925,6 +932,68 @@ Error Composer::execute() return error; } +// Composer HAL 2.2 + +Error Composer::getPerFrameMetadataKeys( + Display display, std::vector* outKeys) { + if (!mClient_2_2) { + return Error::UNSUPPORTED; + } + + Error error = kDefaultError; + mClient_2_2->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outKeys = tmpKeys; + }); + + return error; +} + +Error Composer::getRenderIntents(Display display, ColorMode colorMode, + std::vector* outRenderIntents) { + if (!mClient_2_2) { + outRenderIntents->push_back(RenderIntent::COLORIMETRIC); + return Error::NONE; + } + + Error error = kDefaultError; + mClient_2_2->getRenderIntents(display, colorMode, + [&](const auto& tmpError, const auto& tmpKeys) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outRenderIntents = tmpKeys; + }); + + return error; +} + +Error Composer::getDataspaceSaturationMatrix(Dataspace dataspace, mat4* outMatrix) +{ + if (!mClient_2_2) { + *outMatrix = mat4(); + return Error::NONE; + } + + Error error = kDefaultError; + mClient_2_2->getDataspaceSaturationMatrix(dataspace, [&](const auto& tmpError, const auto& tmpMatrix) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outMatrix = mat4(tmpMatrix.data()); + }); + + return error; +} + CommandReader::~CommandReader() { resetData(); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 98f2f9d387..08901f685f 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -38,12 +39,13 @@ namespace Hwc2 { using android::frameworks::vr::composer::V1_0::IVrComposerClient; -using android::hardware::graphics::common::V1_0::ColorMode; using android::hardware::graphics::common::V1_0::ColorTransform; using android::hardware::graphics::common::V1_0::Hdr; using android::hardware::graphics::common::V1_0::Transform; +using android::hardware::graphics::common::V1_1::ColorMode; using android::hardware::graphics::common::V1_1::Dataspace; using android::hardware::graphics::common::V1_1::PixelFormat; +using android::hardware::graphics::common::V1_1::RenderIntent; using android::hardware::graphics::composer::V2_1::Config; using android::hardware::graphics::composer::V2_1::Display; @@ -114,9 +116,6 @@ public: float* outMaxLuminance, float* outMaxAverageLuminance, float* outMinLuminance) = 0; - virtual Error getPerFrameMetadataKeys( - Display display, std::vector* outKeys) = 0; - virtual Error getReleaseFences(Display display, std::vector* outLayers, std::vector* outReleaseFences) = 0; @@ -132,7 +131,7 @@ public: virtual Error setClientTarget(Display display, uint32_t slot, const sp& target, int acquireFence, Dataspace dataspace, const std::vector& damage) = 0; - virtual Error setColorMode(Display display, ColorMode mode) = 0; + virtual Error setColorMode(Display display, ColorMode mode, RenderIntent renderIntent) = 0; virtual Error setColorTransform(Display display, const float* matrix, ColorTransform hint) = 0; virtual Error setOutputBuffer(Display display, const native_handle_t* buffer, int releaseFence) = 0; @@ -175,6 +174,13 @@ public: const std::vector& visible) = 0; virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0; virtual Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) = 0; + + // Composer HAL 2.2 + virtual Error getPerFrameMetadataKeys( + Display display, std::vector* outKeys) = 0; + virtual Error getRenderIntents(Display display, ColorMode colorMode, + std::vector* outRenderIntents) = 0; + virtual Error getDataspaceSaturationMatrix(Dataspace dataspace, mat4* outMatrix) = 0; }; namespace impl { @@ -306,9 +312,6 @@ public: Error getHdrCapabilities(Display display, std::vector* outTypes, float* outMaxLuminance, float* outMaxAverageLuminance, float* outMinLuminance) override; - Error getPerFrameMetadataKeys( - Display display, std::vector* outKeys) override; - Error getReleaseFences(Display display, std::vector* outLayers, std::vector* outReleaseFences) override; @@ -324,7 +327,7 @@ public: Error setClientTarget(Display display, uint32_t slot, const sp& target, int acquireFence, Dataspace dataspace, const std::vector& damage) override; - Error setColorMode(Display display, ColorMode mode) override; + Error setColorMode(Display display, ColorMode mode, RenderIntent renderIntent) override; Error setColorTransform(Display display, const float* matrix, ColorTransform hint) override; Error setOutputBuffer(Display display, const native_handle_t* buffer, int releaseFence) override; @@ -364,6 +367,13 @@ public: Error setLayerZOrder(Display display, Layer layer, uint32_t z) override; Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) override; + // Composer HAL 2.2 + Error getPerFrameMetadataKeys( + Display display, std::vector* outKeys) override; + Error getRenderIntents(Display display, ColorMode colorMode, + std::vector* outRenderIntents) override; + Error getDataspaceSaturationMatrix(Dataspace dataspace, mat4* outMatrix) override; + private: class CommandWriter : public CommandWriterBase { public: diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 2686788ade..5f94bb4202 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -50,6 +50,7 @@ namespace Hwc2 = android::Hwc2; using android::ui::ColorMode; using android::ui::Dataspace; using android::ui::PixelFormat; +using android::ui::RenderIntent; namespace { @@ -369,6 +370,19 @@ Error Display::getColorModes(std::vector* outModes) const return static_cast(intError); } +Error Display::getRenderIntents(ColorMode colorMode, + std::vector* outRenderIntents) const +{ + auto intError = mComposer.getRenderIntents(mId, colorMode, outRenderIntents); + return static_cast(intError); +} + +Error Display::getDataspaceSaturationMatrix(Dataspace dataspace, android::mat4* outMatrix) +{ + auto intError = mComposer.getDataspaceSaturationMatrix(dataspace, outMatrix); + return static_cast(intError); +} + std::vector> Display::getConfigs() const { std::vector> configs; @@ -526,9 +540,9 @@ Error Display::setClientTarget(uint32_t slot, const sp& target, return static_cast(intError); } -Error Display::setColorMode(ColorMode mode) +Error Display::setColorMode(ColorMode mode, RenderIntent renderIntent) { - auto intError = mComposer.setColorMode(mId, mode); + auto intError = mComposer.setColorMode(mId, mode, renderIntent); return static_cast(intError); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 9b870e3ed9..e5779d40d1 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -212,6 +212,11 @@ public: std::unordered_map* outTypes); [[clang::warn_unused_result]] Error getColorModes( std::vector* outModes) const; + [[clang::warn_unused_result]] Error getRenderIntents( + android::ui::ColorMode colorMode, + std::vector* outRenderIntents) const; + [[clang::warn_unused_result]] Error getDataspaceSaturationMatrix( + android::ui::Dataspace dataspace, android::mat4* outMatrix); // Doesn't call into the HWC2 device, so no errors are possible std::vector> getConfigs() const; @@ -236,7 +241,8 @@ public: const android::sp& acquireFence, android::ui::Dataspace dataspace); [[clang::warn_unused_result]] Error setColorMode( - android::ui::ColorMode mode); + android::ui::ColorMode mode, + android::ui::RenderIntent renderIntent); [[clang::warn_unused_result]] Error setColorTransform( const android::mat4& matrix, android_color_transform_t hint); [[clang::warn_unused_result]] Error setOutputBuffer( diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 29e2727b3e..8db8aa6cd0 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -330,17 +330,20 @@ std::vector HWComposer::getColorModes(int32_t displayId) const { return modes; } -status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode) { +status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode, + ui::RenderIntent renderIntent) { if (!isValidDisplay(displayId)) { ALOGE("setActiveColorMode: Display %d is not valid", displayId); return BAD_INDEX; } auto& displayData = mDisplayData[displayId]; - auto error = displayData.hwcDisplay->setColorMode(mode); + auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent); if (error != HWC2::Error::None) { - ALOGE("setActiveConfig: Failed to set color mode %d on display %d: " - "%s (%d)", mode, displayId, to_string(error).c_str(), + ALOGE("setActiveConfig: Failed to set color mode %d" + "with render intent %d on display %d: " + "%s (%d)", mode, renderIntent, displayId, + to_string(error).c_str(), static_cast(error)); return UNKNOWN_ERROR; } @@ -841,6 +844,44 @@ std::unique_ptr HWComposer::getHdrCapabilities( return capabilities; } +std::vector HWComposer::getRenderIntents(int32_t displayId, + ui::ColorMode colorMode) const { + if (!isValidDisplay(displayId)) { + ALOGE("getRenderIntents: Attempted to access invalid display %d", + displayId); + return {}; + } + + std::vector renderIntents; + auto error = mDisplayData[displayId].hwcDisplay->getRenderIntents(colorMode, &renderIntents); + if (error != HWC2::Error::None) { + ALOGE("getColorModes failed for display %d: %s (%d)", displayId, + to_string(error).c_str(), static_cast(error)); + return std::vector(); + } + + return renderIntents; +} + +mat4 HWComposer::getDataspaceSaturationMatrix(int32_t displayId, ui::Dataspace dataspace) { + if (!isValidDisplay(displayId)) { + ALOGE("getDataSpaceSaturationMatrix: Attempted to access invalid display %d", + displayId); + return {}; + } + + mat4 matrix; + auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace, + &matrix); + if (error != HWC2::Error::None) { + ALOGE("getDataSpaceSaturationMatrix failed for display %d: %s (%d)", displayId, + to_string(error).c_str(), static_cast(error)); + return mat4(); + } + + return matrix; +} + // Converts a PixelFormat to a human-readable string. Max 11 chars. // (Could use a table of prefab String8 objects.) /* diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 6e2e156abd..e86d6211c8 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -137,6 +137,11 @@ public: // Returns the HDR capabilities of the given display std::unique_ptr getHdrCapabilities(int32_t displayId); + // Returns the available RenderIntent of the given display. + std::vector getRenderIntents(int32_t displayId, ui::ColorMode colorMode) const; + + mat4 getDataspaceSaturationMatrix(int32_t displayId, ui::Dataspace dataspace); + // Events handling --------------------------------------------------------- // Returns true if successful, false otherwise. The @@ -161,7 +166,8 @@ public: std::vector getColorModes(int32_t displayId) const; - status_t setActiveColorMode(int32_t displayId, ui::ColorMode mode); + status_t setActiveColorMode(int32_t displayId, ui::ColorMode mode, + ui::RenderIntent renderIntent); bool isUsingVrComposer() const; diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 1eda900f47..1fc310025d 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -302,6 +302,7 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE, mesh.getByteStride(), mesh.getPositions()); + // TODO(b/73825729) Refactor this code block to handle BT2020 color space properly. // DISPLAY_P3 is the only supported wide color output if (mPlatformHasWideColor && mOutputDataSpace == Dataspace::DISPLAY_P3) { Description wideColorState = mState; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c5bd0eb20e..5be7951972 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -106,6 +106,7 @@ using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; using ui::ColorMode; using ui::Dataspace; +using ui::RenderIntent; namespace { class ConditionalLock { @@ -1007,7 +1008,7 @@ void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, hw->getDisplayType()); hw->setActiveColorMode(mode); - getHwComposer().setActiveColorMode(type, mode); + getHwComposer().setActiveColorMode(type, mode, RenderIntent::COLORIMETRIC); } diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index c048c583f2..0705b5c7f8 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -46,8 +46,8 @@ using testing::Mock; using testing::Return; using testing::SetArgPointee; -using android::hardware::graphics::common::V1_0::ColorMode; using android::hardware::graphics::common::V1_0::Hdr; +using android::hardware::graphics::common::V1_1::ColorMode; using android::Hwc2::Error; using android::Hwc2::IComposer; using android::Hwc2::IComposerClient; diff --git a/services/surfaceflinger/tests/unittests/MockComposer.h b/services/surfaceflinger/tests/unittests/MockComposer.h index 00e565b75c..8be277915e 100644 --- a/services/surfaceflinger/tests/unittests/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/MockComposer.h @@ -27,12 +27,13 @@ class GraphicBuffer; namespace Hwc2 { namespace mock { -using android::hardware::graphics::common::V1_0::ColorMode; using android::hardware::graphics::common::V1_0::ColorTransform; using android::hardware::graphics::common::V1_0::Hdr; using android::hardware::graphics::common::V1_0::Transform; +using android::hardware::graphics::common::V1_1::ColorMode; using android::hardware::graphics::common::V1_1::Dataspace; using android::hardware::graphics::common::V1_1::PixelFormat; +using android::hardware::graphics::common::V1_1::RenderIntent; using android::hardware::graphics::composer::V2_1::Config; using android::hardware::graphics::composer::V2_1::Display; @@ -75,13 +76,14 @@ public: MOCK_METHOD5(getHdrCapabilities, Error(Display, std::vector*, float*, float*, float*)); MOCK_METHOD2(getPerFrameMetadataKeys, Error(Display, std::vector*)); + MOCK_METHOD2(getDataspaceSaturationMatrix, Error(Dataspace, mat4*)); MOCK_METHOD3(getReleaseFences, Error(Display, std::vector*, std::vector*)); MOCK_METHOD2(presentDisplay, Error(Display, int*)); MOCK_METHOD2(setActiveConfig, Error(Display, Config)); MOCK_METHOD6(setClientTarget, Error(Display, uint32_t, const sp&, int, Dataspace, const std::vector&)); - MOCK_METHOD2(setColorMode, Error(Display, ColorMode)); + MOCK_METHOD3(setColorMode, Error(Display, ColorMode, RenderIntent)); MOCK_METHOD3(setColorTransform, Error(Display, const float*, ColorTransform)); MOCK_METHOD3(setOutputBuffer, Error(Display, const native_handle_t*, int)); MOCK_METHOD2(setPowerMode, Error(Display, IComposerClient::PowerMode)); @@ -107,6 +109,7 @@ public: Error(Display, Layer, const std::vector&)); MOCK_METHOD3(setLayerZOrder, Error(Display, Layer, uint32_t)); MOCK_METHOD4(setLayerInfo, Error(Display, Layer, uint32_t, uint32_t)); + MOCK_METHOD3(getRenderIntents, Error(Display, ColorMode, std::vector*)); }; } // namespace mock -- cgit v1.2.3-59-g8ed1b From 2713c30843816d3511b39b85a2c268a2b7682047 Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Wed, 28 Mar 2018 17:07:36 -0700 Subject: Early wake-up for transitions (1/2) On some devices it's very likely that we fall into GL comp during app transitions. However, SF offsets are chosen in a way such that the time to finish a frame is just too tight to be completely jank free when hitting GL composition in SurfaceFlinger. Thus, we introduce the concept of a separate early offset, and wakeup SurfaceFlinger at that time if we think that hitting GL comp is likely, or we already hit GL comp in the last frame. Test: Open app, check vsync offsets in systrace Test: Open many dialogs/apps to fall into GPU comp. Bug: 75985430 Change-Id: Ie17e30c4575359fa11bb8912f68dcafe3e569ddb Merged-In: Ie17e30c4575359fa11bb8912f68dcafe3e569ddb --- libs/gui/SurfaceComposerClient.cpp | 11 ++- libs/gui/include/gui/ISurfaceComposer.h | 5 + libs/gui/include/gui/SurfaceComposerClient.h | 2 + services/surfaceflinger/BufferLayer.cpp | 1 + services/surfaceflinger/BufferLayerConsumer.cpp | 1 + services/surfaceflinger/DispSync.cpp | 27 ++++++ services/surfaceflinger/DispSync.h | 5 + .../RenderEngine/GLES20RenderEngine.cpp | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 41 +++++---- services/surfaceflinger/SurfaceFlinger.h | 6 ++ services/surfaceflinger/VSyncModulator.h | 101 +++++++++++++++++++++ 11 files changed, 184 insertions(+), 17 deletions(-) create mode 100644 services/surfaceflinger/VSyncModulator.h (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index bbf681ea90..63560c4b89 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -101,7 +101,8 @@ void ComposerService::composerServiceDied() SurfaceComposerClient::Transaction::Transaction(const Transaction& other) : mForceSynchronous(other.mForceSynchronous), mTransactionNestCount(other.mTransactionNestCount), - mAnimation(other.mAnimation) { + mAnimation(other.mAnimation), + mEarlyWakeup(other.mEarlyWakeup) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; } @@ -157,9 +158,13 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { if (mAnimation) { flags |= ISurfaceComposer::eAnimation; } + if (mEarlyWakeup) { + flags |= ISurfaceComposer::eEarlyWakeup; + } mForceSynchronous = false; mAnimation = false; + mEarlyWakeup = false; sf->setTransactionState(composerStates, displayStates, flags); mStatus = NO_ERROR; @@ -185,6 +190,10 @@ void SurfaceComposerClient::Transaction::setAnimationTransaction() { mAnimation = true; } +void SurfaceComposerClient::Transaction::setEarlyWakeup() { + mEarlyWakeup = true; +} + layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp& sc) { if (mComposerStates.count(sc) == 0) { // we don't have it, add an initialized layer_state to our list diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 3591090172..e40157206d 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -61,6 +61,11 @@ public: enum { eSynchronous = 0x01, eAnimation = 0x02, + + // Indicates that this transaction will likely result in a lot of layers being composed, and + // thus, SurfaceFlinger should wake-up earlier to avoid missing frame deadlines. In this + // case SurfaceFlinger will wake up at (sf vsync offset - debug.sf.early_phase_offset_ns) + eEarlyWakeup = 0x04 }; enum { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index ffc22f6437..377fe68c41 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -154,6 +154,7 @@ public: uint32_t mForceSynchronous = 0; uint32_t mTransactionNestCount = 0; bool mAnimation = false; + bool mEarlyWakeup = false; int mStatus = NO_ERROR; @@ -273,6 +274,7 @@ public: const Rect& displayRect); void setDisplaySize(const sp& token, uint32_t width, uint32_t height); void setAnimationTransaction(); + void setEarlyWakeup(); }; status_t destroySurface(const sp& id); diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 82300e679f..2aa4cd3578 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -778,6 +778,7 @@ bool BufferLayer::getOpacityForFormat(uint32_t format) { } void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { + ATRACE_CALL(); const State& s(getDrawingState()); computeGeometry(renderArea, getBE().mMesh, useIdentityTransform); diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 6b4f5dbfb0..87333d0ffd 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -356,6 +356,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, } status_t BufferLayerConsumer::bindTextureImageLocked() { + ATRACE_CALL(); mRE.checkErrors(); if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == nullptr) { diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index 9e01fd0d8d..7acbd11bc5 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -209,6 +209,28 @@ public: return BAD_VALUE; } + status_t changePhaseOffset(DispSync::Callback* callback, nsecs_t phase) { + if (kTraceDetailedInfo) ATRACE_CALL(); + Mutex::Autolock lock(mMutex); + + for (size_t i = 0; i < mEventListeners.size(); i++) { + if (mEventListeners[i].mCallback == callback) { + EventListener& listener = mEventListeners.editItemAt(i); + const nsecs_t oldPhase = listener.mPhase; + listener.mPhase = phase; + + // Pretend that the last time this event was handled at the same frame but with the + // new offset to allow for a seamless offset change without double-firing or + // skipping. + listener.mLastEventTime -= (oldPhase - phase); + mCond.signal(); + return NO_ERROR; + } + } + + return BAD_VALUE; + } + // This method is only here to handle the !SurfaceFlinger::hasSyncFramework // case. bool hasAnyEventListeners() { @@ -487,6 +509,11 @@ status_t DispSync::removeEventListener(Callback* callback) { return mThread->removeEventListener(callback); } +status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) { + Mutex::Autolock lock(mMutex); + return mThread->changePhaseOffset(callback, phase); +} + void DispSync::setPeriod(nsecs_t period) { Mutex::Autolock lock(mMutex); mPeriod = period; diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index 9336f4dd86..077256ac11 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -113,6 +113,11 @@ public: // DispSync object. status_t removeEventListener(Callback* callback); + // changePhaseOffset changes the phase offset of an already-registered event callback. The + // method will make sure that there is no skipping or double-firing on the listener per frame, + // even when changing the offsets multiple times. + status_t changePhaseOffset(Callback* callback, nsecs_t phase); + // computeNextRefresh computes when the next refresh is expected to begin. // The periodOffset value can be used to move forward or backward; an // offset of zero is the next refresh, -1 is the previous refresh, 1 is diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 1fc310025d..0fb3d28d05 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -293,6 +293,7 @@ void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) } void GLES20RenderEngine::drawMesh(const Mesh& mesh) { + ATRACE_CALL(); if (mesh.getTexCoordsSize()) { glEnableVertexAttribArray(Program::texCoords); glVertexAttribPointer(Program::texCoords, mesh.getTexCoordsSize(), GL_FLOAT, GL_FALSE, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5be7951972..183c1eb07c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -296,6 +296,12 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize)); mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize; + property_get("debug.sf.early_phase_offset_ns", value, "0"); + const int earlyWakeupOffsetOffsetNs = atoi(value); + ALOGI_IF(earlyWakeupOffsetOffsetNs != 0, "Enabling separate early offset"); + mVsyncModulator.setPhaseOffsets(sfVsyncPhaseOffsetNs - earlyWakeupOffsetOffsetNs, + sfVsyncPhaseOffsetNs); + // We should be reading 'persist.sys.sf.color_saturation' here // but since /data may be encrypted, we need to wait until after vold // comes online to attempt to read the property. The property is @@ -522,19 +528,10 @@ public: return; } - // Remove the listener with the old offset - status_t err = mDispSync->removeEventListener( - static_cast(this)); + status_t err = mDispSync->changePhaseOffset(static_cast(this), + mPhaseOffset); if (err != NO_ERROR) { - ALOGE("error unregistering vsync callback: %s (%d)", - strerror(-err), err); - } - - // Add a listener with the new offset - err = mDispSync->addEventListener(mName, mPhaseOffset, - static_cast(this)); - if (err != NO_ERROR) { - ALOGE("error registering vsync callback: %s (%d)", + ALOGE("error changing vsync offset: %s (%d)", strerror(-err), err); } } @@ -623,6 +620,7 @@ void SurfaceFlinger::init() { mSFEventThread = std::make_unique(mSfEventThreadSource.get(), *this, true, "sfEventThread"); mEventQueue->setEventThread(mSFEventThread.get()); + mVsyncModulator.setEventThread(mSFEventThread.get()); // Get a RenderEngine for the given display / config (can't fail) getBE().mRenderEngine = @@ -1498,6 +1496,7 @@ void SurfaceFlinger::handleMessageRefresh() { mHadClientComposition = mHadClientComposition || getBE().mHwc->hasClientComposition(displayDevice->getHwcDisplayId()); } + mVsyncModulator.setLastFrameUsedRenderEngine(mHadClientComposition); mLayersWithQueuedFrames.clear(); } @@ -2122,6 +2121,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // with mStateLock held to guarantee that mCurrentState won't change // until the transaction is committed. + mVsyncModulator.setTransactionStart(VSyncModulator::TransactionStart::NORMAL); transactionFlags = getTransactionFlags(eTransactionMask); handleTransactionLocked(transactionFlags); @@ -3070,7 +3070,13 @@ uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) { } uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { + return setTransactionFlags(flags, VSyncModulator::TransactionStart::NORMAL); +} + +uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, + VSyncModulator::TransactionStart transactionStart) { uint32_t old = android_atomic_or(flags, &mTransactionFlags); + mVsyncModulator.setTransactionStart(transactionStart); if ((old & flags)==0) { // wake the server up signalTransaction(); } @@ -3159,7 +3165,10 @@ void SurfaceFlinger::setTransactionState( } // this triggers the transaction - setTransactionFlags(transactionFlags); + const auto start = (flags & eEarlyWakeup) + ? VSyncModulator::TransactionStart::EARLY + : VSyncModulator::TransactionStart::NORMAL; + setTransactionFlags(transactionFlags, start); // if this is a synchronous transaction, wait for it to take effect // before returning. @@ -4099,9 +4108,9 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, colorizer.bold(result); result.append("DispSync configuration: "); colorizer.reset(result); - result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, " - "present offset %" PRId64 " ns (refresh %" PRId64 " ns)", - vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, + result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, early sf phase %" PRId64 + " ns, present offset %" PRId64 " ns (refresh %" PRId64 " ns)", + vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, mVsyncModulator.getEarlyPhaseOffset(), dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod()); result.append("\n"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 89c9cfda19..a29d1d7475 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,7 @@ #include "Barrier.h" #include "DisplayDevice.h" #include "DispSync.h" +#include "EventThread.h" #include "FrameTracker.h" #include "LayerStats.h" #include "LayerVector.h" @@ -61,6 +63,7 @@ #include "SurfaceInterceptor.h" #include "SurfaceTracing.h" #include "StartPropertySetThread.h" +#include "VSyncModulator.h" #include "DisplayHardware/HWC2.h" #include "DisplayHardware/HWComposer.h" @@ -492,6 +495,7 @@ private: uint32_t peekTransactionFlags(); // Can only be called from the main thread or with mStateLock held uint32_t setTransactionFlags(uint32_t flags); + uint32_t setTransactionFlags(uint32_t flags, VSyncModulator::TransactionStart transactionStart); void commitTransaction(); bool containsAnyInvalidClientState(const Vector& states); uint32_t setClientStateLocked(const ComposerState& composerState); @@ -765,6 +769,8 @@ private: std::unique_ptr mEventControlThread; sp mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; + VSyncModulator mVsyncModulator; + // Can only accessed from the main thread, these members // don't need synchronization State mDrawingState{LayerVector::StateSet::Drawing}; diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/VSyncModulator.h new file mode 100644 index 0000000000..3126debed4 --- /dev/null +++ b/services/surfaceflinger/VSyncModulator.h @@ -0,0 +1,101 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include + +using namespace android::surfaceflinger; + +namespace android { + +/* + * Modulates the vsync-offsets depending on current SurfaceFlinger state. + */ +class VSyncModulator { +public: + + enum TransactionStart { + EARLY, + NORMAL + }; + + // Sets the phase offsets + // + // early: the phase offset when waking up early. May be the same as late, in which case we don't + // shift offsets. + // late: the regular sf phase offset. + void setPhaseOffsets(nsecs_t early, nsecs_t late) { + mEarlyPhaseOffset = early; + mLatePhaseOffset = late; + mPhaseOffset = late; + } + + nsecs_t getEarlyPhaseOffset() const { + return mEarlyPhaseOffset; + } + + void setEventThread(EventThread* eventThread) { + mEventThread = eventThread; + } + + void setTransactionStart(TransactionStart transactionStart) { + if (transactionStart == mTransactionStart) return; + mTransactionStart = transactionStart; + updatePhaseOffsets(); + } + + void setLastFrameUsedRenderEngine(bool re) { + if (re == mLastFrameUsedRenderEngine) return; + mLastFrameUsedRenderEngine = re; + updatePhaseOffsets(); + } + +private: + + void updatePhaseOffsets() { + + // Do not change phase offsets if disabled. + if (mEarlyPhaseOffset == mLatePhaseOffset) return; + + if (mTransactionStart == TransactionStart::EARLY || mLastFrameUsedRenderEngine) { + if (mPhaseOffset != mEarlyPhaseOffset) { + if (mEventThread) { + mEventThread->setPhaseOffset(mEarlyPhaseOffset); + } + mPhaseOffset = mEarlyPhaseOffset; + } + } else { + if (mPhaseOffset != mLatePhaseOffset) { + if (mEventThread) { + mEventThread->setPhaseOffset(mLatePhaseOffset); + } + mPhaseOffset = mLatePhaseOffset; + } + } + } + + nsecs_t mLatePhaseOffset = 0; + nsecs_t mEarlyPhaseOffset = 0; + EventThread* mEventThread = nullptr; + std::atomic mPhaseOffset = 0; + std::atomic mTransactionStart = TransactionStart::NORMAL; + std::atomic mLastFrameUsedRenderEngine = false; +}; + +} // namespace android -- cgit v1.2.3-59-g8ed1b From dd9b2ae8500d85a6aba82de15e8b40d14a921ca6 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Thu, 1 Mar 2018 16:22:45 -0800 Subject: [SurfaceFinger] Adds auto color mode support in SurfaceFlinger. This patch adds auto color mode support in SurfaceFlinger. For Auto Awesome Color milestone 1, we expect the hardware composer is capable of handling P3 layers, meaning if the hardware composer is given P3 layers, it will strech the color from Display P3 to the pannel native color space. Hardware composer may punt sRGB layers back to SurfaceFlinger, in this case, we fall back to RenderEngine. We will set the destination data space to Display P3 when the layers are mixed color spaces, and set the destination data space as SRGB if they are all SRGB layers. BUG: 73824924 BUG: 73825729 Test: Build Change-Id: I577841b14de0cfe8c29f8aa30bee8621c5d72976 --- services/surfaceflinger/DisplayDevice.cpp | 26 ++- services/surfaceflinger/DisplayDevice.h | 24 ++- services/surfaceflinger/Layer.cpp | 15 ++ services/surfaceflinger/Layer.h | 7 + services/surfaceflinger/RenderArea.h | 5 +- services/surfaceflinger/SurfaceFlinger.cpp | 318 +++++++++++++++++++---------- services/surfaceflinger/SurfaceFlinger.h | 26 ++- 7 files changed, 283 insertions(+), 138 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 58a774b7e2..d90ab1dfed 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -55,6 +55,7 @@ namespace android { using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; using android::ui::ColorMode; +using android::ui::RenderIntent; /* * Initialize the display to the specified values. @@ -75,8 +76,8 @@ DisplayDevice::DisplayDevice( std::unique_ptr renderSurface, int displayWidth, int displayHeight, - bool supportWideColor, - bool supportHdr, + bool hasWideColorGamut, + bool hasHdr10, int initialPowerMode) : lastCompositionHadVisibleLayers(false), mFlinger(flinger), @@ -98,8 +99,8 @@ DisplayDevice::DisplayDevice( mActiveConfig(0), mActiveColorMode(ColorMode::NATIVE), mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY), - mDisplayHasWideColor(supportWideColor), - mDisplayHasHdr(supportHdr) + mHasWideColorGamut(hasWideColorGamut), + mHasHdr10(hasHdr10) { // clang-format on @@ -268,6 +269,14 @@ ColorMode DisplayDevice::getActiveColorMode() const { return mActiveColorMode; } +RenderIntent DisplayDevice::getActiveRenderIntent() const { + return mActiveRenderIntent; +} + +void DisplayDevice::setActiveRenderIntent(RenderIntent renderIntent) { + mActiveRenderIntent = renderIntent; +} + void DisplayDevice::setColorTransform(const mat4& transform) { const bool isIdentity = (transform == mat4()); mColorTransform = @@ -279,10 +288,15 @@ android_color_transform_t DisplayDevice::getColorTransform() const { } void DisplayDevice::setCompositionDataSpace(ui::Dataspace dataspace) { + mCompositionDataSpace = dataspace; ANativeWindow* const window = mNativeWindow.get(); native_window_set_buffers_data_space(window, static_cast(dataspace)); } +ui::Dataspace DisplayDevice::getCompositionDataSpace() const { + return mCompositionDataSpace; +} + // ---------------------------------------------------------------------------- void DisplayDevice::setLayerStack(uint32_t stack) { @@ -464,8 +478,8 @@ void DisplayDevice::dump(String8& result) const { tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]); auto const surface = static_cast(window); ui::Dataspace dataspace = surface->getBuffersDataSpace(); - result.appendFormat(" wideColor=%d, hdr=%d, colorMode=%s, dataspace: %s (%d)\n", - mDisplayHasWideColor, mDisplayHasHdr, + result.appendFormat(" wideColorGamut=%d, hdr10=%d, colorMode=%s, dataspace: %s (%d)\n", + mHasWideColorGamut, mHasHdr10, decodeColorMode(mActiveColorMode).c_str(), dataspaceDetails(static_cast(dataspace)).c_str(), dataspace); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index e844d115c2..bedf76589f 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -84,8 +84,8 @@ public: std::unique_ptr renderSurface, int displayWidth, int displayHeight, - bool supportWideColor, - bool supportHdr, + bool hasWideColorGamut, + bool hasHdr10, int initialPowerMode); // clang-format on @@ -135,8 +135,8 @@ public: // machine happy without actually queueing a buffer if nothing has changed status_t beginFrame(bool mustRecompose) const; status_t prepareFrame(HWComposer& hwc); - bool getWideColorSupport() const { return mDisplayHasWideColor; } - bool getHdrSupport() const { return mDisplayHasHdr; } + bool hasWideColorGamut() const { return mHasWideColorGamut; } + bool hasHdr10() const { return mHasHdr10; } void swapBuffers(HWComposer& hwc) const; @@ -165,9 +165,12 @@ public: ui::ColorMode getActiveColorMode() const; void setActiveColorMode(ui::ColorMode mode); + ui::RenderIntent getActiveRenderIntent() const; + void setActiveRenderIntent(ui::RenderIntent renderIntent); android_color_transform_t getColorTransform() const; void setColorTransform(const mat4& transform); void setCompositionDataSpace(ui::Dataspace dataspace); + ui::Dataspace getCompositionDataSpace() const; /* ------------------------------------------------------------------------ * Display active config management. @@ -241,14 +244,17 @@ private: int mActiveConfig; // current active color mode ui::ColorMode mActiveColorMode; + // Current active render intent. + ui::RenderIntent mActiveRenderIntent; + ui::Dataspace mCompositionDataSpace; // Current color transform android_color_transform_t mColorTransform; // Need to know if display is wide-color capable or not. // Initialized by SurfaceFlinger when the DisplayDevice is created. // Fed to RenderEngine during composition. - bool mDisplayHasWideColor; - bool mDisplayHasHdr; + bool mHasWideColorGamut; + bool mHasHdr10; }; struct DisplayDeviceState { @@ -290,9 +296,9 @@ public: bool isSecure() const override { return mDevice->isSecure(); } bool needsFiltering() const override { return mDevice->needsFiltering(); } Rect getSourceCrop() const override { return mSourceCrop; } - bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); } - ui::ColorMode getActiveColorMode() const override { - return mDevice->getActiveColorMode(); + bool getWideColorSupport() const override { return mDevice->hasWideColorGamut(); } + ui::Dataspace getDataSpace() const override { + return mDevice->getCompositionDataSpace(); } private: diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9d356d86c7..8c0050ee47 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1643,6 +1643,21 @@ bool Layer::detachChildren() { return true; } +// Dataspace::UNKNOWN, Dataspace::SRGB, Dataspace::SRGB_LINEAR, +// Dataspace::V0_SRGB and Dataspace::V0_SRGB_LINEAR are considered legacy +// SRGB data space for now. +// Note that Dataspace::V0_SRGB and Dataspace::V0_SRGB_LINEAR are not legacy +// data space, however since framework doesn't distinguish them out of legacy +// SRGB, we have to treat them as the same for now. +bool Layer::isLegacySrgbDataSpace() const { + // TODO(lpy) b/77652630, need to figure out when UNKNOWN can be treated as SRGB. + return mDrawingState.dataSpace == ui::Dataspace::UNKNOWN || + mDrawingState.dataSpace == ui::Dataspace::SRGB || + mDrawingState.dataSpace == ui::Dataspace::SRGB_LINEAR || + mDrawingState.dataSpace == ui::Dataspace::V0_SRGB || + mDrawingState.dataSpace == ui::Dataspace::V0_SRGB_LINEAR; +} + void Layer::setParent(const sp& layer) { mCurrentParent = layer; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8d2a0488dc..d382a1a173 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -297,6 +297,13 @@ public: bool reparent(const sp& newParentHandle); bool detachChildren(); + // Before color management is introduced, contents on Android have to be + // desaturated in order to match what they appears like visually. + // With color management, these contents will appear desaturated, thus + // needed to be saturated so that they match what they are designed for + // visually. When returns true, legacy SRGB data space is passed to HWC. + bool isLegacySrgbDataSpace() const; + // If we have received a new buffer this frame, we will pass its surface // damage down to hardware composer. Otherwise, we must send a region with // one empty rect. diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index bf0707f13b..4f812fc81b 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -25,15 +25,14 @@ public: virtual bool isSecure() const = 0; virtual bool needsFiltering() const = 0; virtual Rect getSourceCrop() const = 0; + virtual bool getWideColorSupport() const = 0; + virtual ui::Dataspace getDataSpace() const = 0; virtual void render(std::function drawLayers) { drawLayers(); } int getReqHeight() const { return mReqHeight; }; int getReqWidth() const { return mReqWidth; }; Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; - virtual bool getWideColorSupport() const = 0; - virtual ui::ColorMode getActiveColorMode() const = 0; - status_t updateDimensions(); private: diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 183c1eb07c..abd3a9efcc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -157,6 +157,31 @@ bool useTrebleTestingOverride() { return std::string(value) == "true"; } +DisplayColorSetting toDisplayColorSetting(int value) { + switch(value) { + case 0: + return DisplayColorSetting::MANAGED; + case 1: + return DisplayColorSetting::UNMANAGED; + case 2: + return DisplayColorSetting::ENHANCED; + default: + return DisplayColorSetting::MANAGED; + } +} + +std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) { + switch(displayColorSetting) { + case DisplayColorSetting::MANAGED: + return std::string("Natural Mode"); + case DisplayColorSetting::UNMANAGED: + return std::string("Saturated Mode"); + case DisplayColorSetting::ENHANCED: + return std::string("Auto Color Mode"); + } + return std::string("Unknown Display Color Setting"); +} + NativeWindowSurface::~NativeWindowSurface() = default; namespace impl { @@ -690,6 +715,9 @@ void SurfaceFlinger::init() { ALOGE("Run StartPropertySetThread failed!"); } + mLegacySrgbSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY, + Dataspace::SRGB_LINEAR); + ALOGV("Done initializing"); } @@ -697,14 +725,13 @@ void SurfaceFlinger::readPersistentProperties() { char value[PROPERTY_VALUE_MAX]; property_get("persist.sys.sf.color_saturation", value, "1.0"); - mSaturation = atof(value); - ALOGV("Saturation is set to %.2f", mSaturation); + mGlobalSaturationFactor = atof(value); + ALOGV("Saturation is set to %.2f", mGlobalSaturationFactor); property_get("persist.sys.sf.native_mode", value, "0"); - mForceNativeColorMode = atoi(value) == 1; - if (mForceNativeColorMode) { - ALOGV("Forcing native color mode"); - } + mDisplayColorSetting = toDisplayColorSetting(atoi(value)); + ALOGV("Display Color Setting is set to %s.", + decodeDisplayColorSetting(mDisplayColorSetting).c_str()); } void SurfaceFlinger::startBootAnim() { @@ -989,11 +1016,12 @@ ColorMode SurfaceFlinger::getActiveColorMode(const sp& display) { } void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, - ColorMode mode) { + ColorMode mode, Dataspace dataSpace) { int32_t type = hw->getDisplayType(); ColorMode currentMode = hw->getActiveColorMode(); + Dataspace currentDataSpace = hw->getCompositionDataSpace(); - if (mode == currentMode) { + if (mode == currentMode && dataSpace == currentDataSpace) { return; } @@ -1002,11 +1030,29 @@ void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, return; } - ALOGD("Set active color mode: %s (%d), type=%d", decodeColorMode(mode).c_str(), mode, - hw->getDisplayType()); - hw->setActiveColorMode(mode); - getHwComposer().setActiveColorMode(type, mode, RenderIntent::COLORIMETRIC); + hw->setCompositionDataSpace(dataSpace); + // Natural Mode means it's color managed and the color must be right, + // thus we pick RenderIntent::COLORIMETRIC as render intent. + // Native Mode means the display is not color managed, and whichever + // render intent is picked doesn't matter, thus return + // RenderIntent::COLORIMETRIC as default here. + RenderIntent renderIntent = RenderIntent::COLORIMETRIC; + + // In Auto Color Mode, we want to strech to panel color space, right now + // only the built-in display supports it. + if (mDisplayColorSetting == DisplayColorSetting::ENHANCED && + mBuiltinDisplaySupportsEnhance && + hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) { + renderIntent = RenderIntent::ENHANCE; + } + hw->setActiveRenderIntent(renderIntent); + getHwComposer().setActiveColorMode(type, mode, renderIntent); + + ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), type=%d", + decodeColorMode(mode).c_str(), mode, + decodeRenderIntent(renderIntent).c_str(), renderIntent, + hw->getDisplayType()); } @@ -1037,7 +1083,7 @@ status_t SurfaceFlinger::setActiveColorMode(const sp& display, ALOGW("Attempt to set active color mode %s %d for virtual display", decodeColorMode(mMode).c_str(), mMode); } else { - mFlinger.setActiveColorModeInternal(hw, mMode); + mFlinger.setActiveColorModeInternal(hw, mMode, Dataspace::UNKNOWN); } return true; } @@ -1072,7 +1118,7 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp& display, std::unique_ptr capabilities = getBE().mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId()); if (capabilities) { - if (displayDevice->getWideColorSupport() && !displayDevice->getHdrSupport()) { + if (displayDevice->hasWideColorGamut() && !displayDevice->hasHdr10()) { // insert HDR10 as we will force client composition for HDR10 // layers std::vector types = capabilities->getSupportedHdrTypes(); @@ -1821,75 +1867,80 @@ void SurfaceFlinger::rebuildLayerStacks() { } mat4 SurfaceFlinger::computeSaturationMatrix() const { - if (mSaturation == 1.0f) { + if (mGlobalSaturationFactor == 1.0f) { return mat4(); } // Rec.709 luma coefficients float3 luminance{0.213f, 0.715f, 0.072f}; - luminance *= 1.0f - mSaturation; + luminance *= 1.0f - mGlobalSaturationFactor; return mat4( - vec4{luminance.r + mSaturation, luminance.r, luminance.r, 0.0f}, - vec4{luminance.g, luminance.g + mSaturation, luminance.g, 0.0f}, - vec4{luminance.b, luminance.b, luminance.b + mSaturation, 0.0f}, + vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f}, + vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f}, + vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f}, vec4{0.0f, 0.0f, 0.0f, 1.0f} ); } -// pickColorMode translates a given dataspace into the best available color mode. -// Currently only support sRGB and Display-P3. -ColorMode SurfaceFlinger::pickColorMode(Dataspace dataSpace) const { - if (mForceNativeColorMode) { - return ColorMode::NATIVE; +// Returns a dataspace that fits all visible layers. The returned dataspace +// can only be one of +// +// - Dataspace::V0_SRGB +// - Dataspace::DISPLAY_P3 +// - Dataspace::V0_SCRGB_LINEAR +// TODO(b/73825729) Add BT2020 data space. +ui::Dataspace SurfaceFlinger::getBestDataspace( + const sp& displayDevice) const { + Dataspace bestDataspace = Dataspace::V0_SRGB; + for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + switch (layer->getDataSpace()) { + case Dataspace::V0_SCRGB: + case Dataspace::V0_SCRGB_LINEAR: + // return immediately + return Dataspace::V0_SCRGB_LINEAR; + case Dataspace::BT2020_PQ: + case Dataspace::BT2020_ITU_PQ: + // Historically, HDR dataspaces are ignored by SurfaceFlinger. But + // since SurfaceFlinger simulates HDR support now, it should honor + // them unless there is also native support. + if (!displayDevice->hasHdr10()) { + return Dataspace::V0_SCRGB_LINEAR; + } + break; + case Dataspace::DISPLAY_P3: + bestDataspace = Dataspace::DISPLAY_P3; + break; + default: + break; + } } - switch (dataSpace) { - // treat Unknown as regular SRGB buffer, since that's what the rest of the - // system expects. - case Dataspace::UNKNOWN: - case Dataspace::SRGB: - case Dataspace::V0_SRGB: - return ColorMode::SRGB; - break; + return bestDataspace; +} +// Pick the ColorMode / Dataspace for the display device. +// TODO(b/73825729) Add BT2020 color mode. +void SurfaceFlinger::pickColorMode(const sp& displayDevice, + ColorMode* outMode, Dataspace* outDataSpace) const { + if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) { + *outMode = ColorMode::NATIVE; + *outDataSpace = Dataspace::UNKNOWN; + return; + } + + switch (getBestDataspace(displayDevice)) { case Dataspace::DISPLAY_P3: - return ColorMode::DISPLAY_P3; + case Dataspace::V0_SCRGB_LINEAR: + *outMode = ColorMode::DISPLAY_P3; + *outDataSpace = Dataspace::DISPLAY_P3; break; - default: - // TODO (courtneygo): Do we want to assert an error here? - ALOGE("No color mode mapping for %s (%#x)", - dataspaceDetails(static_cast(dataSpace)).c_str(), - dataSpace); - return ColorMode::SRGB; + *outMode = ColorMode::SRGB; + *outDataSpace = Dataspace::V0_SRGB; break; } } -Dataspace SurfaceFlinger::bestTargetDataSpace( - Dataspace a, Dataspace b, bool hasHdr) const { - // Only support sRGB and Display-P3 right now. - if (a == Dataspace::DISPLAY_P3 || b == Dataspace::DISPLAY_P3) { - return Dataspace::DISPLAY_P3; - } - if (a == Dataspace::V0_SCRGB_LINEAR || b == Dataspace::V0_SCRGB_LINEAR) { - return Dataspace::DISPLAY_P3; - } - if (a == Dataspace::V0_SCRGB || b == Dataspace::V0_SCRGB) { - return Dataspace::DISPLAY_P3; - } - if (!hasHdr) { - if (a == Dataspace::BT2020_PQ || b == Dataspace::BT2020_PQ) { - return Dataspace::DISPLAY_P3; - } - if (a == Dataspace::BT2020_ITU_PQ || b == Dataspace::BT2020_ITU_PQ) { - return Dataspace::DISPLAY_P3; - } - } - - return Dataspace::V0_SRGB; -} - void SurfaceFlinger::setUpHWComposer() { ATRACE_CALL(); ALOGV("setUpHWComposer"); @@ -1970,7 +2021,7 @@ void SurfaceFlinger::setUpHWComposer() { for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { if ((layer->getDataSpace() == Dataspace::BT2020_PQ || layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && - !displayDevice->getHdrSupport()) { + !displayDevice->hasHdr10()) { layer->forceClientComposition(hwcId); } @@ -1984,19 +2035,10 @@ void SurfaceFlinger::setUpHWComposer() { } if (hasWideColorDisplay) { - ColorMode newColorMode; - Dataspace newDataSpace = Dataspace::V0_SRGB; - - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace, - displayDevice->getHdrSupport()); - ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)", - layer->getName().string(), dataspaceDetails(static_cast(layer->getDataSpace())).c_str(), - layer->getDataSpace(), dataspaceDetails(static_cast(newDataSpace)).c_str(), newDataSpace); - } - newColorMode = pickColorMode(newDataSpace); - - setActiveColorModeInternal(displayDevice, newColorMode); + ColorMode colorMode; + Dataspace dataSpace; + pickColorMode(displayDevice, &colorMode, &dataSpace); + setActiveColorModeInternal(displayDevice, colorMode, dataSpace); } } @@ -2204,29 +2246,40 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { sp SurfaceFlinger::setupNewDisplayDeviceInternal( const wp& display, int hwcId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer) { - bool hasWideColorSupport = false; + bool hasWideColorGamut = false; if (hasWideColorDisplay) { - std::vector modes = getHwComposer().getColorModes(state.type); + std::vector modes = getHwComposer().getColorModes(hwcId); for (ColorMode colorMode : modes) { switch (colorMode) { case ColorMode::DISPLAY_P3: case ColorMode::ADOBE_RGB: case ColorMode::DCI_P3: - hasWideColorSupport = true; + hasWideColorGamut = true; break; + // TODO(lpy) Handle BT2020, BT2100_PQ and BT2100_HLG properly. default: break; } + + std::vector renderIntents = getHwComposer().getRenderIntents(hwcId, + colorMode); + if (state.type == DisplayDevice::DISPLAY_PRIMARY) { + for (auto intent : renderIntents) { + if (intent == RenderIntent::ENHANCE) { + mBuiltinDisplaySupportsEnhance = true; + break; + } + } + } } } - bool hasHdrSupport = false; - std::unique_ptr hdrCapabilities = - getHwComposer().getHdrCapabilities(state.type); + bool hasHdr10 = false; + std::unique_ptr hdrCapabilities = getHwComposer().getHdrCapabilities(hwcId); if (hdrCapabilities) { const std::vector types = hdrCapabilities->getSupportedHdrTypes(); auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10); - hasHdrSupport = iter != types.cend(); + hasHdr10 = iter != types.cend(); } auto nativeWindowSurface = mCreateNativeWindowSurface(producer); @@ -2260,18 +2313,19 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( sp hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow, dispSurface, std::move(renderSurface), displayWidth, displayHeight, - hasWideColorSupport, hasHdrSupport, initialPowerMode); + hasWideColorGamut, hasHdr10, initialPowerMode); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); } ColorMode defaultColorMode = ColorMode::NATIVE; - if (hasWideColorSupport) { + Dataspace defaultDataSpace = Dataspace::UNKNOWN; + if (hasWideColorGamut) { defaultColorMode = ColorMode::SRGB; + defaultDataSpace = Dataspace::V0_SRGB; } - setActiveColorModeInternal(hw, defaultColorMode); - hw->setCompositionDataSpace(Dataspace::UNKNOWN); + setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); hw->setDisplayName(state.displayName); @@ -2822,23 +2876,27 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev const Region bounds(displayDevice->bounds()); const DisplayRenderArea renderArea(displayDevice); const auto hwcId = displayDevice->getHwcDisplayId(); + const bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId); + const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId); + const bool skipClientColorTransform = getBE().mHwc->hasCapability( + HWC2::Capability::SkipClientColorTransform); + ATRACE_INT("hasClientComposition", hasClientComposition); mat4 oldColorMatrix; - const bool applyColorMatrix = !getBE().mHwc->hasDeviceComposition(hwcId) && - !getBE().mHwc->hasCapability(HWC2::Capability::SkipClientColorTransform); + mat4 legacySrgbSaturationMatrix = mLegacySrgbSaturationMatrix; + const bool applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; if (applyColorMatrix) { - mat4 colorMatrix = mColorMatrix * mDaltonizer(); + mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer(); oldColorMatrix = getRenderEngine().setupColorTransform(colorMatrix); + legacySrgbSaturationMatrix = colorMatrix * legacySrgbSaturationMatrix; } - bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId); if (hasClientComposition) { ALOGV("hasClientComposition"); Dataspace outputDataspace = Dataspace::UNKNOWN; - if (displayDevice->getWideColorSupport() && - displayDevice->getActiveColorMode() == ColorMode::DISPLAY_P3) { - outputDataspace = Dataspace::DISPLAY_P3; + if (displayDevice->hasWideColorGamut()) { + outputDataspace = displayDevice->getCompositionDataSpace(); } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); @@ -2855,7 +2913,6 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev } // Never touch the framebuffer if we don't have any framebuffer layers - const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId); if (hasDeviceComposition) { // when using overlays, we assume a fully transparent framebuffer // NOTE: we could reduce how much we need to clear, for instance @@ -2930,7 +2987,20 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev break; } case HWC2::Composition::Client: { + // Only apply saturation matrix layer that is legacy SRGB dataspace + // when auto color mode is on. + bool restore = false; + mat4 savedMatrix; + if (mDisplayColorSetting == DisplayColorSetting::ENHANCED && + layer->isLegacySrgbDataSpace()) { + savedMatrix = + getRenderEngine().setupColorTransform(legacySrgbSaturationMatrix); + restore = true; + } layer->draw(renderArea, clip); + if (restore) { + getRenderEngine().setupColorTransform(savedMatrix); + } break; } default: @@ -4004,7 +4074,7 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { void SurfaceFlinger::dumpWideColorInfo(String8& result) const { result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay); - result.appendFormat("forceNativeColorMode: %d\n", mForceNativeColorMode); + result.appendFormat("DisplayColorSetting: %d\n", mDisplayColorSetting); // TODO: print out if wide-color mode is active or not @@ -4500,15 +4570,22 @@ status_t SurfaceFlinger::onTransact( return NO_ERROR; } case 1022: { // Set saturation boost - mSaturation = std::max(0.0f, std::min(data.readFloat(), 2.0f)); + mGlobalSaturationFactor = std::max(0.0f, std::min(data.readFloat(), 2.0f)); invalidateHwcGeometry(); repaintEverything(); return NO_ERROR; } case 1023: { // Set native mode - mForceNativeColorMode = data.readInt32() == 1; + int32_t value = data.readInt32(); + if (value > 2) { + return BAD_VALUE; + } + if (value == 2 && !mBuiltinDisplaySupportsEnhance) { + return BAD_VALUE; + } + mDisplayColorSetting = toDisplayColorSetting(value); invalidateHwcGeometry(); repaintEverything(); return NO_ERROR; @@ -4535,6 +4612,23 @@ status_t SurfaceFlinger::onTransact( reply->writeBool(mTracing.isEnabled()); return NO_ERROR; } + // Is a DisplayColorSetting supported? + case 1027: { + int32_t value = data.readInt32(); + switch (value) { + case 0: + reply->writeBool(hasWideColorDisplay); + return NO_ERROR; + case 1: + reply->writeBool(true); + return NO_ERROR; + case 2: + reply->writeBool(mBuiltinDisplaySupportsEnhance); + return NO_ERROR; + default: + return BAD_VALUE; + } + } } } return err; @@ -4602,6 +4696,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, mCrop(crop), mFlinger(flinger), mChildrenOnly(childrenOnly) {} + const Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { const Layer::State& layerState(mLayer->getDrawingState()); return Rect(layerState.active.w, layerState.active.h); @@ -4610,7 +4705,15 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, int getWidth() const override { return mLayer->getDrawingState().active.w; } bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } - const Transform& getTransform() const { return mTransform; } + Rect getSourceCrop() const override { + if (mCrop.isEmpty()) { + return getBounds(); + } else { + return mCrop; + } + } + bool getWideColorSupport() const override { return false; } + Dataspace getDataSpace() const override { return Dataspace::UNKNOWN; } class ReparentForDrawing { public: @@ -4639,16 +4742,6 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, } } - Rect getSourceCrop() const override { - if (mCrop.isEmpty()) { - return getBounds(); - } else { - return mCrop; - } - } - bool getWideColorSupport() const override { return false; } - ColorMode getActiveColorMode() const override { return ColorMode::NATIVE; } - private: const sp mLayer; const Rect mCrop; @@ -4820,9 +4913,8 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, } Dataspace outputDataspace = Dataspace::UNKNOWN; - if (renderArea.getWideColorSupport() && - renderArea.getActiveColorMode() == ColorMode::DISPLAY_P3) { - outputDataspace = Dataspace::DISPLAY_P3; + if (renderArea.getWideColorSupport()) { + outputDataspace = renderArea.getDataSpace(); } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a29d1d7475..14028fffe6 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -123,6 +123,12 @@ enum { eTransactionMask = 0x0f, }; +enum class DisplayColorSetting : int32_t { + MANAGED = 0, + UNMANAGED = 1, + ENHANCED = 2, +}; + // A thin interface to abstract creating instances of Surface (gui/Surface.h) to // use as a NativeWindow. class NativeWindowSurface { @@ -467,7 +473,9 @@ private: bool stateLockHeld); // Called on the main thread in response to setActiveColorMode() - void setActiveColorModeInternal(const sp& hw, ui::ColorMode colorMode); + void setActiveColorModeInternal(const sp& hw, + ui::ColorMode colorMode, + ui::Dataspace dataSpace); // Returns whether the transaction actually modified any state bool handleMessageTransaction(); @@ -641,9 +649,10 @@ private: // Given a dataSpace, returns the appropriate color_mode to use // to display that dataSpace. - ui::ColorMode pickColorMode(ui::Dataspace dataSpace) const; - ui::Dataspace bestTargetDataSpace(ui::Dataspace a, ui::Dataspace b, - bool hasHdr) const; + ui::Dataspace getBestDataspace(const sp& displayDevice) const; + void pickColorMode(const sp& displayDevice, + ui::ColorMode* outMode, + ui::Dataspace* outDataSpace) const; mat4 computeSaturationMatrix() const; @@ -846,7 +855,6 @@ private: size_t mNumLayers; - // Verify that transaction is being called by an approved process: // either AID_GRAPHICS or AID_SYSTEM. status_t CheckTransactCodeCredentials(uint32_t code); @@ -856,8 +864,12 @@ private: static bool useVrFlinger; std::thread::id mMainThreadId; - float mSaturation = 1.0f; - bool mForceNativeColorMode = false; + DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::MANAGED; + // Applied on sRGB layers when the render intent is non-colorimetric. + mat4 mLegacySrgbSaturationMatrix; + // Applied globally. + float mGlobalSaturationFactor = 1.0f; + bool mBuiltinDisplaySupportsEnhance = false; using CreateBufferQueueFunction = std::function* /* outProducer */, -- cgit v1.2.3-59-g8ed1b From 38e9a56173c64a9640c6c390735a398d32752650 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 10 Apr 2018 16:24:20 -0700 Subject: [SurfaceFlinger] Fix color mode switch. Previously we didn't take render intent into account when switch color mode, switching from staturated to automatic and then to natural/boosted doesn't work. BUG: 73824924 BUG: 73825729 Test: Built, flashed to taimen, and verified with Color settings. Change-Id: I4556e82e2bab10113d05c446fc4bb3351a3e65a6 --- services/surfaceflinger/SurfaceFlinger.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index abd3a9efcc..a8680e2dd8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1020,18 +1020,8 @@ void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, int32_t type = hw->getDisplayType(); ColorMode currentMode = hw->getActiveColorMode(); Dataspace currentDataSpace = hw->getCompositionDataSpace(); + RenderIntent currentRenderIntent = hw->getActiveRenderIntent(); - if (mode == currentMode && dataSpace == currentDataSpace) { - return; - } - - if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { - ALOGW("Trying to set config for virtual display"); - return; - } - - hw->setActiveColorMode(mode); - hw->setCompositionDataSpace(dataSpace); // Natural Mode means it's color managed and the color must be right, // thus we pick RenderIntent::COLORIMETRIC as render intent. // Native Mode means the display is not color managed, and whichever @@ -1046,6 +1036,19 @@ void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) { renderIntent = RenderIntent::ENHANCE; } + + if (mode == currentMode && dataSpace == currentDataSpace && + renderIntent == currentRenderIntent) { + return; + } + + if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) { + ALOGW("Trying to set config for virtual display"); + return; + } + + hw->setActiveColorMode(mode); + hw->setCompositionDataSpace(dataSpace); hw->setActiveRenderIntent(renderIntent); getHwComposer().setActiveColorMode(type, mode, renderIntent); -- cgit v1.2.3-59-g8ed1b From f15c3be1e8eab73da2dd3b2a7e6215302dae4314 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Thu, 12 Apr 2018 12:56:58 +0100 Subject: Fix transaction phase offsets There are cases where we have multiple source of transactions in one frame. In these cases, if a NORMAL gets submitted after an EARLY, it will override the early one which will cause to use the wrong phase offset for this frame. In some cases an EARLY was then still scheduled before the frame happened, so any kind of phase offset was observeable, which looked like drifting. Fix this by making sure an EARLY frame stays an EARLY frame. Test: Open app. Ensure by looking really closely that vsync-sf is happening at the supposed offset. Bug: 75985430 Change-Id: I5dbf097d314767493b0f06b9eb6dd7c6b2f93919 --- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- services/surfaceflinger/VSyncModulator.h | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 183c1eb07c..982107b4d8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2121,7 +2121,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // with mStateLock held to guarantee that mCurrentState won't change // until the transaction is committed. - mVsyncModulator.setTransactionStart(VSyncModulator::TransactionStart::NORMAL); + mVsyncModulator.onTransactionHandled(); transactionFlags = getTransactionFlags(eTransactionMask); handleTransactionLocked(transactionFlags); diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/VSyncModulator.h index 3126debed4..3e5800e2a2 100644 --- a/services/surfaceflinger/VSyncModulator.h +++ b/services/surfaceflinger/VSyncModulator.h @@ -55,11 +55,20 @@ public: } void setTransactionStart(TransactionStart transactionStart) { - if (transactionStart == mTransactionStart) return; + // An early transaction stays an early transaction. + if (transactionStart == mTransactionStart || mTransactionStart == TransactionStart::EARLY) { + return; + } mTransactionStart = transactionStart; updatePhaseOffsets(); } + void onTransactionHandled() { + if (mTransactionStart == TransactionStart::NORMAL) return; + mTransactionStart = TransactionStart::NORMAL; + updatePhaseOffsets(); + } + void setLastFrameUsedRenderEngine(bool re) { if (re == mLastFrameUsedRenderEngine) return; mLastFrameUsedRenderEngine = re; -- cgit v1.2.3-59-g8ed1b From c7a25adf66b138de66814383540905b83cf12a01 Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Thu, 12 Apr 2018 11:45:09 -0700 Subject: SF: Fix repaint everything logic This solves the same problem with dirty regions not being updated as Ia7a3dc15c96626a213c4459dac4f695d91540fb5, but it is better in a couple of ways: 1) It no longer updates dirty regions from a binder thread, which was likely causing the memory corruption in b/77919748. 2) It removes the distinction between repaintEverything and repaintEverythingLocked, which is not necessary since both operations in repaintEverything (updating an atomic and signaling a transaction) are threadsafe. Bug: 77335744 Bug: 77546473 Bug: 77919748 Test: Manual - on an ASAN build, played TouchLatency bouncy ball while toggling between GL and HWC composition; doesn't crash whereas it would crash in a matter of a couple minutes before Change-Id: Iecadfecb40e87e400a301de2dcad1664e154982d --- services/surfaceflinger/SurfaceFlinger.cpp | 19 ++++--------------- services/surfaceflinger/SurfaceFlinger.h | 2 -- 2 files changed, 4 insertions(+), 17 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a8680e2dd8..726d155586 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1387,7 +1387,7 @@ void SurfaceFlinger::onRefreshReceived(int sequenceId, if (sequenceId != getBE().mComposerSequenceId) { return; } - repaintEverythingLocked(); + repaintEverything(); } void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) { @@ -1949,7 +1949,7 @@ void SurfaceFlinger::setUpHWComposer() { ALOGV("setUpHWComposer"); for (size_t dpy=0 ; dpygetDirtyRegion(false).isEmpty(); + bool dirty = !mDisplays[dpy]->getDirtyRegion(mRepaintEverything).isEmpty(); bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0; bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers; @@ -3716,7 +3716,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp& hw, mVisibleRegionsDirty = true; mHasPoweredOff = true; - repaintEverythingLocked(); + repaintEverything(); struct sched_param param = {0}; param.sched_priority = 1; @@ -4637,22 +4637,11 @@ status_t SurfaceFlinger::onTransact( return err; } -void SurfaceFlinger::repaintEverythingLocked() { +void SurfaceFlinger::repaintEverything() { android_atomic_or(1, &mRepaintEverything); - for (size_t dpy = 0; dpy < mDisplays.size(); dpy++) { - const sp& displayDevice(mDisplays[dpy]); - const Rect bounds(displayDevice->getBounds()); - displayDevice->dirtyRegion.orSelf(Region(bounds)); - } signalTransaction(); } -void SurfaceFlinger::repaintEverything() { - ConditionalLock _l(mStateLock, - std::this_thread::get_id() != mMainThreadId); - repaintEverythingLocked(); -} - // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope class WindowDisconnector { public: diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 14028fffe6..33706dafe9 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -312,8 +312,6 @@ public: // force full composition on all displays void repaintEverything(); - // Can only be called from the main thread or with mStateLock held - void repaintEverythingLocked(); // returns the default Display sp getDefaultDisplayDevice() const { -- cgit v1.2.3-59-g8ed1b From 50da5043ad224fd6b6024ed73785a9502bf7978d Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 9 Apr 2018 13:49:37 -0700 Subject: Set window to transparent when screenshotting layer. Set the screenshot to transparent instead of black. This allows the system to draw a color behind without having to crop out the area that may not be drawn into. Bug: 76442549 Test: When going to recents, area not drawn from layers is now transparent instead of black. Test: Transaction_test#CaptureTransparent Change-Id: Id535eb753d3d1cae82658cd33423ce588aaa62f8 --- services/surfaceflinger/DisplayDevice.h | 3 ++- services/surfaceflinger/RenderArea.cpp | 9 +++++++++ services/surfaceflinger/RenderArea.h | 12 ++++++++++-- services/surfaceflinger/SurfaceFlinger.cpp | 5 +++-- services/surfaceflinger/tests/Transaction_test.cpp | 18 ++++++++++++++++++ 5 files changed, 42 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index e844d115c2..61ce30ca86 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -281,7 +281,8 @@ public: rotation) {} DisplayRenderArea(const sp device, Rect sourceCrop, uint32_t reqHeight, uint32_t reqWidth, ISurfaceComposer::Rotation rotation) - : RenderArea(reqHeight, reqWidth, rotation), mDevice(device), mSourceCrop(sourceCrop) {} + : RenderArea(reqHeight, reqWidth, CaptureFill::OPAQUE, rotation), mDevice(device), + mSourceCrop(sourceCrop) {} const Transform& getTransform() const override { return mDevice->getTransform(); } Rect getBounds() const override { return mDevice->getBounds(); } diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp index 6225df134d..46ec8e68ba 100644 --- a/services/surfaceflinger/RenderArea.cpp +++ b/services/surfaceflinger/RenderArea.cpp @@ -2,6 +2,15 @@ namespace android { +float RenderArea::getCaptureFillValue(CaptureFill captureFill) { + switch(captureFill) { + case CaptureFill::CLEAR: + return 0.0f; + case CaptureFill::OPAQUE: + default: + return 1.0f; + } +} /* * Checks that the requested width and height are valid and updates them to the render area * dimensions if they are set to 0 diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index bf0707f13b..62a3d5b333 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -9,10 +9,15 @@ namespace android { class RenderArea { + public: - RenderArea(uint32_t reqHeight, uint32_t reqWidth, + enum class CaptureFill {CLEAR, OPAQUE}; + + static float getCaptureFillValue(CaptureFill captureFill); + + RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill, ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone) - : mReqHeight(reqHeight), mReqWidth(reqWidth) { + : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) { mRotationFlags = Transform::fromRotation(rotation); } @@ -36,10 +41,13 @@ public: status_t updateDimensions(); + CaptureFill getCaptureFill() const { return mCaptureFill; }; + private: uint32_t mReqHeight; uint32_t mReqWidth; Transform::orientation_flags mRotationFlags; + CaptureFill mCaptureFill; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 183c1eb07c..781a30ccf5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4597,7 +4597,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, public: LayerRenderArea(SurfaceFlinger* flinger, const sp& layer, const Rect crop, int32_t reqWidth, int32_t reqHeight, bool childrenOnly) - : RenderArea(reqHeight, reqWidth), + : RenderArea(reqHeight, reqWidth, CaptureFill::CLEAR), mLayer(layer), mCrop(crop), mFlinger(flinger), @@ -4834,8 +4834,9 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, renderArea.getRotationFlags()); engine.disableTexturing(); + const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill()); // redraw the screen entirely... - engine.clearWithColor(0, 0, 0, 1); + engine.clearWithColor(0, 0, 0, alpha); traverseLayers([&](Layer* layer) { if (filtering) layer->setFiltering(true); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 176c691c6a..a0f12f1438 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2358,6 +2358,24 @@ TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) { mCapture->expectChildColor(0, 0); } +TEST_F(ScreenCaptureTest, CaptureTransparent) { + sp child = + mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + + fillSurfaceRGBA8(child, 200, 200, 200); + + SurfaceComposerClient::Transaction().show(child).apply(true); + + auto childHandle = child->getHandle(); + + // Captures child + ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20}); + mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255}); + // Area outside of child's bounds is transparent. + mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0}); +} + // In the following tests we verify successful skipping of a parent layer, // so we use the same verification logic and only change how we mutate -- cgit v1.2.3-59-g8ed1b From 6266589793ddd9769a649a6b5f61ef115179572b Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Mon, 16 Apr 2018 11:07:44 -0700 Subject: [SurfaceFlinger] Extend HDR support. Previously we stored HDR10 support in DisplayDevice. This patch extends and generalizes the support to HLG and Dolby Vision. Minor: Adapt Hdr type from HAL. BUG: 73825729 BUG: 77156734 Test: Build, flash, watch Youtube HDR Change-Id: Id642bc9482523b4646814dca9ecfb1f043987dc5 --- libs/ui/HdrCapabilities.cpp | 6 ++-- libs/ui/include/ui/GraphicTypes.h | 1 + libs/ui/include/ui/HdrCapabilities.h | 7 ++-- services/surfaceflinger/DisplayDevice.cpp | 22 +++++++++++-- services/surfaceflinger/DisplayDevice.h | 8 +++-- services/surfaceflinger/DisplayHardware/HWC2.cpp | 13 +++----- services/surfaceflinger/DisplayHardware/HWC2.h | 2 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 18 +++++----- .../surfaceflinger/DisplayHardware/HWComposer.h | 4 +-- services/surfaceflinger/SurfaceFlinger.cpp | 38 ++++++++++------------ .../tests/unittests/DisplayTransactionTest.cpp | 2 +- 11 files changed, 68 insertions(+), 53 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp index 755e60c82e..50f9bf13fd 100644 --- a/libs/ui/HdrCapabilities.cpp +++ b/libs/ui/HdrCapabilities.cpp @@ -33,7 +33,7 @@ size_t HdrCapabilities::getFlattenedSize() const { sizeof(mMaxAverageLuminance) + sizeof(mMinLuminance) + sizeof(int32_t) + - mSupportedHdrTypes.size() * sizeof(int32_t); + mSupportedHdrTypes.size() * sizeof(ui::Hdr); } status_t HdrCapabilities::flatten(void* buffer, size_t size) const { @@ -48,7 +48,7 @@ status_t HdrCapabilities::flatten(void* buffer, size_t size) const { reinterpret_cast(buf[2]) = mMinLuminance; buf[3] = static_cast(mSupportedHdrTypes.size()); for (size_t i = 0, c = mSupportedHdrTypes.size(); i < c; ++i) { - buf[4 + i] = mSupportedHdrTypes[i]; + buf[4 + i] = static_cast(mSupportedHdrTypes[i]); } return NO_ERROR; } @@ -78,7 +78,7 @@ status_t HdrCapabilities::unflatten(void const* buffer, size_t size) { if (itemCount) { mSupportedHdrTypes.resize(itemCount); for (size_t i = 0; i < itemCount; ++i) { - mSupportedHdrTypes[i] = buf[4 + i]; + mSupportedHdrTypes[i] = static_cast(buf[4 + i]); } } return NO_ERROR; diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h index bd5722fdb0..0fa819dce8 100644 --- a/libs/ui/include/ui/GraphicTypes.h +++ b/libs/ui/include/ui/GraphicTypes.h @@ -24,6 +24,7 @@ namespace android { namespace ui { +using android::hardware::graphics::common::V1_0::Hdr; using android::hardware::graphics::common::V1_1::ColorMode; using android::hardware::graphics::common::V1_1::Dataspace; using android::hardware::graphics::common::V1_1::PixelFormat; diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h index 925aa1b7b3..4e98c283d1 100644 --- a/libs/ui/include/ui/HdrCapabilities.h +++ b/libs/ui/include/ui/HdrCapabilities.h @@ -21,6 +21,7 @@ #include +#include #include namespace android { @@ -28,7 +29,7 @@ namespace android { class HdrCapabilities : public LightFlattenable { public: - HdrCapabilities(const std::vector& types, + HdrCapabilities(const std::vector& types, float maxLuminance, float maxAverageLuminance, float minLuminance) : mSupportedHdrTypes(types), mMaxLuminance(maxLuminance), @@ -47,7 +48,7 @@ public: ~HdrCapabilities(); - const std::vector& getSupportedHdrTypes() const { + const std::vector& getSupportedHdrTypes() const { return mSupportedHdrTypes; } float getDesiredMaxLuminance() const { return mMaxLuminance; } @@ -61,7 +62,7 @@ public: status_t unflatten(void const* buffer, size_t size); private: - std::vector mSupportedHdrTypes; + std::vector mSupportedHdrTypes; float mMaxLuminance; float mMaxAverageLuminance; float mMinLuminance; diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index d90ab1dfed..cd41662fee 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -55,6 +55,7 @@ namespace android { using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; using android::ui::ColorMode; +using android::ui::Hdr; using android::ui::RenderIntent; /* @@ -77,7 +78,7 @@ DisplayDevice::DisplayDevice( int displayWidth, int displayHeight, bool hasWideColorGamut, - bool hasHdr10, + const HdrCapabilities& hdrCapabilities, int initialPowerMode) : lastCompositionHadVisibleLayers(false), mFlinger(flinger), @@ -100,9 +101,26 @@ DisplayDevice::DisplayDevice( mActiveColorMode(ColorMode::NATIVE), mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY), mHasWideColorGamut(hasWideColorGamut), - mHasHdr10(hasHdr10) + mHasHdr10(false), + mHasHLG(false), + mHasDolbyVision(false) { // clang-format on + for (Hdr hdrType : hdrCapabilities.getSupportedHdrTypes()) { + switch (hdrType) { + case Hdr::HDR10: + mHasHdr10 = true; + break; + case Hdr::HLG: + mHasHLG = true; + break; + case Hdr::DOLBY_VISION: + mHasDolbyVision = true; + break; + default: + ALOGE("UNKNOWN HDR capability: %d", static_cast(hdrType)); + } + } // initialize the display orientation transform. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index b8a890679e..cd0bed6631 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -85,7 +85,7 @@ public: int displayWidth, int displayHeight, bool hasWideColorGamut, - bool hasHdr10, + const HdrCapabilities& hdrCapabilities, int initialPowerMode); // clang-format on @@ -136,7 +136,9 @@ public: status_t beginFrame(bool mustRecompose) const; status_t prepareFrame(HWComposer& hwc); bool hasWideColorGamut() const { return mHasWideColorGamut; } - bool hasHdr10() const { return mHasHdr10; } + bool hasHDR10Support() const { return mHasHdr10; } + bool hasHLGSupport() const { return mHasHLG; } + bool hasDolbyVisionSupport() const { return mHasDolbyVision; } void swapBuffers(HWComposer& hwc) const; @@ -255,6 +257,8 @@ private: // Fed to RenderEngine during composition. bool mHasWideColorGamut; bool mHasHdr10; + bool mHasHLG; + bool mHasDolbyVision; }; struct DisplayDeviceState { diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 5f94bb4202..0667f8d5b6 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -448,26 +448,21 @@ Error Display::supportsDoze(bool* outSupport) const return Error::None; } -Error Display::getHdrCapabilities( - std::unique_ptr* outCapabilities) const +Error Display::getHdrCapabilities(HdrCapabilities* outCapabilities) const { float maxLuminance = -1.0f; float maxAverageLuminance = -1.0f; float minLuminance = -1.0f; - std::vector intTypes; - auto intError = mComposer.getHdrCapabilities(mId, &intTypes, + std::vector types; + auto intError = mComposer.getHdrCapabilities(mId, &types, &maxLuminance, &maxAverageLuminance, &minLuminance); auto error = static_cast(intError); - std::vector types; - for (auto type : intTypes) { - types.push_back(static_cast(type)); - } if (error != Error::None) { return error; } - *outCapabilities = std::make_unique(std::move(types), + *outCapabilities = HdrCapabilities(std::move(types), maxLuminance, maxAverageLuminance, minLuminance); return Error::None; } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index e5779d40d1..aa907eab95 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -228,7 +228,7 @@ public: [[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* outCapabilities) const; + android::HdrCapabilities* outCapabilities) const; [[clang::warn_unused_result]] Error getReleaseFences( std::unordered_map>* outFences) const; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 8db8aa6cd0..0a3ac84db7 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -824,24 +824,22 @@ void HWComposer::clearReleaseFences(int32_t displayId) { mDisplayData[displayId].releaseFences.clear(); } -std::unique_ptr HWComposer::getHdrCapabilities( - int32_t displayId) { +status_t HWComposer::getHdrCapabilities( + int32_t displayId, HdrCapabilities* outCapabilities) { if (!isValidDisplay(displayId)) { ALOGE("getHdrCapabilities: Display %d is not valid", displayId); - return nullptr; + return BAD_INDEX; } auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; - std::unique_ptr capabilities; - auto error = hwcDisplay->getHdrCapabilities(&capabilities); + auto error = hwcDisplay->getHdrCapabilities(outCapabilities); if (error != HWC2::Error::None) { ALOGE("getOutputCapabilities: Failed to get capabilities on display %d:" - " %s (%d)", displayId, to_string(error).c_str(), - static_cast(error)); - return nullptr; + " %s (%d)", displayId, to_string(error).c_str(), + static_cast(error)); + return UNKNOWN_ERROR; } - - return capabilities; + return NO_ERROR; } std::vector HWComposer::getRenderIntents(int32_t displayId, diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index e86d6211c8..138e1f1113 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -134,8 +134,8 @@ public: // it can call this to clear the shared pointers in the release fence map void clearReleaseFences(int32_t displayId); - // Returns the HDR capabilities of the given display - std::unique_ptr getHdrCapabilities(int32_t displayId); + // Fetches the HDR capabilities of the given display + status_t getHdrCapabilities(int32_t displayId, HdrCapabilities* outCapabilities); // Returns the available RenderIntent of the given display. std::vector getRenderIntents(int32_t displayId, ui::ColorMode colorMode) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 57f729bf0b..58e4fbeb17 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -106,6 +106,7 @@ using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; using ui::ColorMode; using ui::Dataspace; +using ui::Hdr; using ui::RenderIntent; namespace { @@ -1118,21 +1119,23 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp& display, return BAD_VALUE; } - std::unique_ptr capabilities = - getBE().mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId()); - if (capabilities) { - if (displayDevice->hasWideColorGamut() && !displayDevice->hasHdr10()) { + HdrCapabilities capabilities; + int status = getBE().mHwc->getHdrCapabilities( + displayDevice->getHwcDisplayId(), &capabilities); + if (status == NO_ERROR) { + if (displayDevice->hasWideColorGamut() && + !displayDevice->hasHDR10Support()) { // insert HDR10 as we will force client composition for HDR10 // layers - std::vector types = capabilities->getSupportedHdrTypes(); - types.push_back(HAL_HDR_HDR10); + std::vector types = capabilities.getSupportedHdrTypes(); + types.push_back(Hdr::HDR10); *outCapabilities = HdrCapabilities(types, - capabilities->getDesiredMaxLuminance(), - capabilities->getDesiredMaxAverageLuminance(), - capabilities->getDesiredMinLuminance()); + capabilities.getDesiredMaxLuminance(), + capabilities.getDesiredMaxAverageLuminance(), + capabilities.getDesiredMinLuminance()); } else { - *outCapabilities = std::move(*capabilities); + *outCapabilities = std::move(capabilities); } } else { return BAD_VALUE; @@ -1906,7 +1909,7 @@ ui::Dataspace SurfaceFlinger::getBestDataspace( // Historically, HDR dataspaces are ignored by SurfaceFlinger. But // since SurfaceFlinger simulates HDR support now, it should honor // them unless there is also native support. - if (!displayDevice->hasHdr10()) { + if (!displayDevice->hasHDR10Support()) { return Dataspace::V0_SCRGB_LINEAR; } break; @@ -2024,7 +2027,7 @@ void SurfaceFlinger::setUpHWComposer() { for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { if ((layer->getDataSpace() == Dataspace::BT2020_PQ || layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && - !displayDevice->hasHdr10()) { + !displayDevice->hasHDR10Support()) { layer->forceClientComposition(hwcId); } @@ -2277,13 +2280,8 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( } } - bool hasHdr10 = false; - std::unique_ptr hdrCapabilities = getHwComposer().getHdrCapabilities(hwcId); - if (hdrCapabilities) { - const std::vector types = hdrCapabilities->getSupportedHdrTypes(); - auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10); - hasHdr10 = iter != types.cend(); - } + HdrCapabilities hdrCapabilities; + getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities); auto nativeWindowSurface = mCreateNativeWindowSurface(producer); auto nativeWindow = nativeWindowSurface->getNativeWindow(); @@ -2316,7 +2314,7 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( sp hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow, dispSurface, std::move(renderSurface), displayWidth, displayHeight, - hasWideColorGamut, hasHdr10, initialPowerMode); + hasWideColorGamut, hdrCapabilities, initialPowerMode); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 0705b5c7f8..2551a9cccd 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -81,7 +81,7 @@ protected: sp build() { return new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, false, mDisplayToken, mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0, - 0, false, false, HWC_POWER_MODE_NORMAL); + 0, false, {}, HWC_POWER_MODE_NORMAL); } FakeDisplayDeviceFactory& setNativeWindow(const sp& nativeWindow) { -- cgit v1.2.3-59-g8ed1b From 2c327ac2840b34848543cc961d16d3dbad102f16 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Thu, 19 Apr 2018 22:06:34 -0700 Subject: [SurfaceFlinger] Plumb getPerFrameMetadataKeys and setLayerPerFrameMetadata. This patch compresses supported metdata types into a bitmask and stores it in DisplayDevice and refactors the code in Hwc2::Layer regarding HdrMetadata. When DisplayDevice is created, the ability of accepting metadata will be queried from hardware composer and stored in DisplayDevice. Hwc2::Layer will construct HdrMetadata to PerFrameMetadata when setPerFrameHdrMetadata is called if the incoming meta data is changed. Previously, setLayerPerFrameMetadata was named as setLayerHdrMetadata, but since we move the responsibility of constructing PerFrameMetadata from ComposerHal to Hwc2::Layer, we change the name to setLayerPerFrameMetadata, which is more generic and matches the HIDL interface. BUG: 77831156 Test: Build and flash Change-Id: I447956f4dcf42c90ceb3d29091cd5034ad91061a Merged-In: I447956f4dcf42c90ceb3d29091cd5034ad91061a --- services/surfaceflinger/BufferLayer.cpp | 2 +- services/surfaceflinger/DisplayDevice.cpp | 4 +- services/surfaceflinger/DisplayDevice.h | 14 ++-- .../surfaceflinger/DisplayHardware/ComposerHal.cpp | 54 ++++---------- .../surfaceflinger/DisplayHardware/ComposerHal.h | 12 +++- services/surfaceflinger/DisplayHardware/HWC2.cpp | 82 +++++++++++++++++++++- services/surfaceflinger/DisplayHardware/HWC2.h | 9 ++- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 21 +++++- .../surfaceflinger/DisplayHardware/HWComposer.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 4 +- services/surfaceflinger/tests/hwc2/Android.bp | 1 - .../tests/unittests/DisplayTransactionTest.cpp | 2 +- .../unittests/mock/DisplayHardware/MockComposer.h | 3 +- 13 files changed, 149 insertions(+), 62 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 57f474b9ea..7fd9d01a51 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -650,7 +650,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) } const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata(); - error = hwcLayer->setHdrMetadata(metadata); + error = hwcLayer->setPerFrameMetadata(displayDevice->getSupportedPerFrameMetadata(), metadata); if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), to_string(error).c_str(), static_cast(error)); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index cd41662fee..7c6302e70a 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -79,6 +79,7 @@ DisplayDevice::DisplayDevice( int displayHeight, bool hasWideColorGamut, const HdrCapabilities& hdrCapabilities, + const int32_t supportedPerFrameMetadata, int initialPowerMode) : lastCompositionHadVisibleLayers(false), mFlinger(flinger), @@ -103,7 +104,8 @@ DisplayDevice::DisplayDevice( mHasWideColorGamut(hasWideColorGamut), mHasHdr10(false), mHasHLG(false), - mHasDolbyVision(false) + mHasDolbyVision(false), + mSupportedPerFrameMetadata(supportedPerFrameMetadata) { // clang-format on for (Hdr hdrType : hdrCapabilities.getSupportedHdrTypes()) { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index cd0bed6631..df5d945405 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -23,17 +23,16 @@ #include -#include - #include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include #include "RenderArea.h" #include "RenderEngine/Surface.h" @@ -86,6 +85,7 @@ public: int displayHeight, bool hasWideColorGamut, const HdrCapabilities& hdrCapabilities, + const int32_t supportedPerFrameMetadata, int initialPowerMode); // clang-format on @@ -131,6 +131,8 @@ public: int32_t getHwcDisplayId() const { return mHwcDisplayId; } const wp& getDisplayToken() const { return mDisplayToken; } + int32_t getSupportedPerFrameMetadata() const { return mSupportedPerFrameMetadata; } + // We pass in mustRecompose so we can keep VirtualDisplaySurface's state // machine happy without actually queueing a buffer if nothing has changed status_t beginFrame(bool mustRecompose) const; @@ -259,6 +261,8 @@ private: bool mHasHdr10; bool mHasHLG; bool mHasDolbyVision; + + const int32_t mSupportedPerFrameMetadata; }; struct DisplayDeviceState { diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index c94c290cb2..37ba4339c3 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -715,48 +715,6 @@ Error Composer::setLayerDataspace(Display display, Layer layer, return Error::NONE; } -Error Composer::setLayerHdrMetadata(Display display, Layer layer, const HdrMetadata& metadata) { - if (!mClient_2_2) { - return Error::UNSUPPORTED; - } - - mWriter.selectDisplay(display); - mWriter.selectLayer(layer); - - std::vector composerMetadata; - using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey; - if (metadata.validTypes & HdrMetadata::SMPTE2086) { - composerMetadata - .insert(composerMetadata.end(), - {{PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X, - metadata.smpte2086.displayPrimaryRed.x}, - {PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y, - metadata.smpte2086.displayPrimaryRed.y}, - {PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X, - metadata.smpte2086.displayPrimaryGreen.x}, - {PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y, - metadata.smpte2086.displayPrimaryGreen.y}, - {PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X, - metadata.smpte2086.displayPrimaryBlue.x}, - {PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y, - metadata.smpte2086.displayPrimaryBlue.y}, - {PerFrameMetadataKey::WHITE_POINT_X, metadata.smpte2086.whitePoint.x}, - {PerFrameMetadataKey::WHITE_POINT_Y, metadata.smpte2086.whitePoint.y}, - {PerFrameMetadataKey::MAX_LUMINANCE, metadata.smpte2086.maxLuminance}, - {PerFrameMetadataKey::MIN_LUMINANCE, metadata.smpte2086.minLuminance}}); - } - if (metadata.validTypes & HdrMetadata::CTA861_3) { - composerMetadata.insert(composerMetadata.end(), - {{PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, - metadata.cta8613.maxContentLightLevel}, - {PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, - metadata.cta8613.maxFrameAverageLightLevel}}); - } - - mWriter.setLayerPerFrameMetadata(composerMetadata); - return Error::NONE; -} - Error Composer::setLayerDisplayFrame(Display display, Layer layer, const IComposerClient::Rect& frame) { @@ -927,6 +885,18 @@ Error Composer::execute() // Composer HAL 2.2 +Error Composer::setLayerPerFrameMetadata(Display display, Layer layer, + const std::vector& perFrameMetadatas) { + if (!mClient_2_2) { + return Error::UNSUPPORTED; + } + + mWriter.selectDisplay(display); + mWriter.selectLayer(layer); + mWriter.setLayerPerFrameMetadata(perFrameMetadatas); + return Error::NONE; +} + Error Composer::getPerFrameMetadataKeys( Display display, std::vector* outKeys) { if (!mClient_2_2) { diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index e17fd67ef7..beee53966f 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -64,6 +64,9 @@ using V2_2::CommandWriterBase; using V2_2::IComposer; using V2_2::IComposerClient; +using PerFrameMetadata = IComposerClient::PerFrameMetadata; +using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey; + class Composer { public: virtual ~Composer() = 0; @@ -160,8 +163,6 @@ public: virtual Error setLayerCompositionType(Display display, Layer layer, IComposerClient::Composition type) = 0; virtual Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) = 0; - virtual Error setLayerHdrMetadata(Display display, Layer layer, - const HdrMetadata& metadata) = 0; virtual Error setLayerDisplayFrame(Display display, Layer layer, const IComposerClient::Rect& frame) = 0; virtual Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) = 0; @@ -176,6 +177,9 @@ public: virtual Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) = 0; // Composer HAL 2.2 + virtual Error setLayerPerFrameMetadata( + Display display, Layer layer, + const std::vector& perFrameMetadatas) = 0; virtual Error getPerFrameMetadataKeys( Display display, std::vector* outKeys) = 0; virtual Error getRenderIntents(Display display, ColorMode colorMode, @@ -353,7 +357,6 @@ public: Error setLayerCompositionType(Display display, Layer layer, IComposerClient::Composition type) override; Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) override; - Error setLayerHdrMetadata(Display display, Layer layer, const HdrMetadata& metadata) override; Error setLayerDisplayFrame(Display display, Layer layer, const IComposerClient::Rect& frame) override; Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) override; @@ -368,6 +371,9 @@ public: Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) override; // Composer HAL 2.2 + Error setLayerPerFrameMetadata( + Display display, Layer layer, + const std::vector& perFrameMetadatas) override; Error getPerFrameMetadataKeys( Display display, std::vector* outKeys) override; Error getRenderIntents(Display display, ColorMode colorMode, diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 0667f8d5b6..3947318262 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -32,6 +32,7 @@ #include #include +#include using android::Fence; using android::FloatRect; @@ -54,6 +55,11 @@ using android::ui::RenderIntent; namespace { +inline bool hasMetadataKey(const std::set& keys, + const Hwc2::PerFrameMetadataKey& key) { + return keys.find(key) != keys.end(); +} + class ComposerCallbackBridge : public Hwc2::IComposerCallback { public: ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId) @@ -370,6 +376,42 @@ Error Display::getColorModes(std::vector* outModes) const return static_cast(intError); } +Error Display::getSupportedPerFrameMetadata(int32_t* outSupportedPerFrameMetadata) const +{ + *outSupportedPerFrameMetadata = 0; + std::vector tmpKeys; + auto intError = mComposer.getPerFrameMetadataKeys(mId, &tmpKeys); + auto error = static_cast(intError); + if (error != Error::None) { + return error; + } + + // Check whether a specific metadata type is supported. A metadata type is considered + // supported if and only if all required fields are supported. + + // SMPTE2086 + std::set keys(tmpKeys.begin(), tmpKeys.end()); + if (hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X) && + hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y) && + hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X) && + hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y) && + hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X) && + hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y) && + hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::WHITE_POINT_X) && + hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::WHITE_POINT_Y) && + hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::MAX_LUMINANCE) && + hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::MIN_LUMINANCE)) { + *outSupportedPerFrameMetadata |= HdrMetadata::Type::SMPTE2086; + } + // CTA861_3 + if (hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL) && + hasMetadataKey(keys, Hwc2::PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL)) { + *outSupportedPerFrameMetadata |= HdrMetadata::Type::CTA861_3; + } + + return Error::None; +} + Error Display::getRenderIntents(ColorMode colorMode, std::vector* outRenderIntents) const { @@ -784,13 +826,49 @@ Error Layer::setDataspace(Dataspace dataspace) return static_cast(intError); } -Error Layer::setHdrMetadata(const android::HdrMetadata& metadata) { +Error Layer::setPerFrameMetadata(const int32_t supportedPerFrameMetadata, + const android::HdrMetadata& metadata) +{ if (metadata == mHdrMetadata) { return Error::None; } mHdrMetadata = metadata; - auto intError = mComposer.setLayerHdrMetadata(mDisplayId, mId, metadata); + int validTypes = mHdrMetadata.validTypes & supportedPerFrameMetadata; + std::vector perFrameMetadatas; + if (validTypes & HdrMetadata::SMPTE2086) { + perFrameMetadatas.insert(perFrameMetadatas.end(), + {{Hwc2::PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X, + mHdrMetadata.smpte2086.displayPrimaryRed.x}, + {Hwc2::PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y, + mHdrMetadata.smpte2086.displayPrimaryRed.y}, + {Hwc2::PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X, + mHdrMetadata.smpte2086.displayPrimaryGreen.x}, + {Hwc2::PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y, + mHdrMetadata.smpte2086.displayPrimaryGreen.y}, + {Hwc2::PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X, + mHdrMetadata.smpte2086.displayPrimaryBlue.x}, + {Hwc2::PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y, + mHdrMetadata.smpte2086.displayPrimaryBlue.y}, + {Hwc2::PerFrameMetadataKey::WHITE_POINT_X, + mHdrMetadata.smpte2086.whitePoint.x}, + {Hwc2::PerFrameMetadataKey::WHITE_POINT_Y, + mHdrMetadata.smpte2086.whitePoint.y}, + {Hwc2::PerFrameMetadataKey::MAX_LUMINANCE, + mHdrMetadata.smpte2086.maxLuminance}, + {Hwc2::PerFrameMetadataKey::MIN_LUMINANCE, + mHdrMetadata.smpte2086.minLuminance}}); + } + + if (validTypes & HdrMetadata::CTA861_3) { + perFrameMetadatas.insert(perFrameMetadatas.end(), + {{Hwc2::PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, + mHdrMetadata.cta8613.maxContentLightLevel}, + {Hwc2::PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, + mHdrMetadata.cta8613.maxFrameAverageLightLevel}}); + } + + auto intError = mComposer.setLayerPerFrameMetadata(mDisplayId, mId, perFrameMetadatas); return static_cast(intError); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index aa907eab95..3ac06ec192 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -27,7 +27,6 @@ #include #include #include - #include #include #include @@ -212,6 +211,10 @@ public: std::unordered_map* outTypes); [[clang::warn_unused_result]] Error getColorModes( std::vector* outModes) const; + // outSupportedPerFrameMetadata is an opaque bitmask to the callers + // but contains HdrMetadata::Type::*. + [[clang::warn_unused_result]] Error getSupportedPerFrameMetadata( + int32_t* outSupportedPerFrameMetadata) const; [[clang::warn_unused_result]] Error getRenderIntents( android::ui::ColorMode colorMode, std::vector* outRenderIntents) const; @@ -318,7 +321,9 @@ public: [[clang::warn_unused_result]] Error setCompositionType(Composition type); [[clang::warn_unused_result]] Error setDataspace( android::ui::Dataspace dataspace); - [[clang::warn_unused_result]] Error setHdrMetadata(const android::HdrMetadata& metadata); + [[clang::warn_unused_result]] Error setPerFrameMetadata( + const int32_t supportedPerFrameMetadata, + const android::HdrMetadata& metadata); [[clang::warn_unused_result]] Error setDisplayFrame( const android::Rect& frame); [[clang::warn_unused_result]] Error setPlaneAlpha(float alpha); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 0a3ac84db7..1bbf039b75 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -842,6 +842,25 @@ status_t HWComposer::getHdrCapabilities( return NO_ERROR; } +int32_t HWComposer::getSupportedPerFrameMetadata(int32_t displayId) const { + if (!isValidDisplay(displayId)) { + ALOGE("getPerFrameMetadataKeys: Attempted to access invalid display %d", + displayId); + return 0; + } + + int32_t supportedMetadata; + auto error = mDisplayData[displayId].hwcDisplay->getSupportedPerFrameMetadata( + &supportedMetadata); + if (error != HWC2::Error::None) { + ALOGE("getPerFrameMetadataKeys failed for display %d: %s (%d)", displayId, + to_string(error).c_str(), static_cast(error)); + return 0; + } + + return supportedMetadata; +} + std::vector HWComposer::getRenderIntents(int32_t displayId, ui::ColorMode colorMode) const { if (!isValidDisplay(displayId)) { @@ -853,7 +872,7 @@ std::vector HWComposer::getRenderIntents(int32_t displayId, std::vector renderIntents; auto error = mDisplayData[displayId].hwcDisplay->getRenderIntents(colorMode, &renderIntents); if (error != HWC2::Error::None) { - ALOGE("getColorModes failed for display %d: %s (%d)", displayId, + ALOGE("getRenderIntents failed for display %d: %s (%d)", displayId, to_string(error).c_str(), static_cast(error)); return std::vector(); } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 138e1f1113..d7f3b08d48 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -24,7 +24,6 @@ #include #include - #include #include #include @@ -137,6 +136,8 @@ public: // Fetches the HDR capabilities of the given display status_t getHdrCapabilities(int32_t displayId, HdrCapabilities* outCapabilities); + int32_t getSupportedPerFrameMetadata(int32_t displayId) const; + // Returns the available RenderIntent of the given display. std::vector getRenderIntents(int32_t displayId, ui::ColorMode colorMode) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 58e4fbeb17..e661f03591 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2314,7 +2314,9 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( sp hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow, dispSurface, std::move(renderSurface), displayWidth, displayHeight, - hasWideColorGamut, hdrCapabilities, initialPowerMode); + hasWideColorGamut, hdrCapabilities, + getHwComposer().getSupportedPerFrameMetadata(hwcId), + initialPowerMode); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); diff --git a/services/surfaceflinger/tests/hwc2/Android.bp b/services/surfaceflinger/tests/hwc2/Android.bp index 6c0e4abcfe..0957d6a903 100644 --- a/services/surfaceflinger/tests/hwc2/Android.bp +++ b/services/surfaceflinger/tests/hwc2/Android.bp @@ -41,7 +41,6 @@ cc_test { "libmath", ], shared_libs: [ - "android.hardware.graphics.common@1.0", "android.hardware.graphics.common@1.1", "libcutils", "libEGL", diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 7257b46501..f39ca009f6 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -80,7 +80,7 @@ protected: sp build() { return new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, false, mDisplayToken, mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0, - 0, false, {}, HWC_POWER_MODE_NORMAL); + 0, false, {}, 0, HWC_POWER_MODE_NORMAL); } FakeDisplayDeviceFactory& setNativeWindow(const sp& nativeWindow) { diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index 8be277915e..267670aca5 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -99,7 +99,8 @@ public: MOCK_METHOD3(setLayerColor, Error(Display, Layer, const IComposerClient::Color&)); MOCK_METHOD3(setLayerCompositionType, Error(Display, Layer, IComposerClient::Composition)); MOCK_METHOD3(setLayerDataspace, Error(Display, Layer, Dataspace)); - MOCK_METHOD3(setLayerHdrMetadata, Error(Display, Layer, const HdrMetadata&)); + MOCK_METHOD3(setLayerPerFrameMetadata, + Error(Display, Layer, const std::vector&)); MOCK_METHOD3(setLayerDisplayFrame, Error(Display, Layer, const IComposerClient::Rect&)); MOCK_METHOD3(setLayerPlaneAlpha, Error(Display, Layer, float)); MOCK_METHOD3(setLayerSidebandStream, Error(Display, Layer, const native_handle_t*)); -- cgit v1.2.3-59-g8ed1b From f59a719fe91b201ea0ef9447ae436457aa29a6d6 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 25 Apr 2018 11:19:31 -0700 Subject: [SurfaceFlinger] Add HLG simulation support. This patch adds GPU fallback configuration in SurfaceFlinger for HLG support, as well as propagate HLG simulation up to frameworks. BUG: 73825729 Test: build, flash Change-Id: I58e52648817b326dee868949c3845f613fd218d6 --- services/surfaceflinger/SurfaceFlinger.cpp | 35 +++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 10 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e661f03591..e12d7ca73d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1123,12 +1123,16 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp& display, int status = getBE().mHwc->getHdrCapabilities( displayDevice->getHwcDisplayId(), &capabilities); if (status == NO_ERROR) { - if (displayDevice->hasWideColorGamut() && - !displayDevice->hasHDR10Support()) { - // insert HDR10 as we will force client composition for HDR10 - // layers + if (displayDevice->hasWideColorGamut()) { std::vector types = capabilities.getSupportedHdrTypes(); - types.push_back(Hdr::HDR10); + // insert HDR10/HLG as we will force client composition for HDR10/HLG + // layers + if (!displayDevice->hasHDR10Support()) { + types.push_back(Hdr::HDR10); + } + if (!displayDevice->hasHLGSupport()) { + types.push_back(Hdr::HLG); + } *outCapabilities = HdrCapabilities(types, capabilities.getDesiredMaxLuminance(), @@ -1904,17 +1908,23 @@ ui::Dataspace SurfaceFlinger::getBestDataspace( case Dataspace::V0_SCRGB_LINEAR: // return immediately return Dataspace::V0_SCRGB_LINEAR; + case Dataspace::DISPLAY_P3: + bestDataspace = Dataspace::DISPLAY_P3; + break; + // Historically, HDR dataspaces are ignored by SurfaceFlinger. But + // since SurfaceFlinger simulates HDR support now, it should honor + // them unless there is also native support. case Dataspace::BT2020_PQ: case Dataspace::BT2020_ITU_PQ: - // Historically, HDR dataspaces are ignored by SurfaceFlinger. But - // since SurfaceFlinger simulates HDR support now, it should honor - // them unless there is also native support. if (!displayDevice->hasHDR10Support()) { return Dataspace::V0_SCRGB_LINEAR; } break; - case Dataspace::DISPLAY_P3: - bestDataspace = Dataspace::DISPLAY_P3; + case Dataspace::BT2020_HLG: + case Dataspace::BT2020_ITU_HLG: + if (!displayDevice->hasHLGSupport()) { + return Dataspace::V0_SCRGB_LINEAR; + } break; default: break; @@ -2030,6 +2040,11 @@ void SurfaceFlinger::setUpHWComposer() { !displayDevice->hasHDR10Support()) { layer->forceClientComposition(hwcId); } + if ((layer->getDataSpace() == Dataspace::BT2020_HLG || + layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && + !displayDevice->hasHLGSupport()) { + layer->forceClientComposition(hwcId); + } if (layer->getForceClientComposition(hwcId)) { ALOGV("[%s] Requesting Client composition", layer->getName().string()); -- cgit v1.2.3-59-g8ed1b From fb069305e90947aeb76b72527f23aa24564f3c87 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 25 Apr 2018 14:34:31 -0700 Subject: [SurfaceFlinger] Adapt min/max luminance from hardware composer. The luminance capability of the display is very important to HDR content. Previously, the minimum and maximum luminance were assumed as 0.0 and 500.0 respectively. This patch adapts the value returned from hardware composer and plumbs the value to RenderEngine. If hardware composer doesn't return valid values, 0.0 and 500.0 are still used as minimum and maximum luminance respectively. BUG: 73825729 BUG: 78574325 Test: Build, flash, watch video. Change-Id: Ie1dc93f5cca7068580d6ae19da43346491196d7c --- libs/ui/HdrCapabilities.cpp | 1 - services/surfaceflinger/DisplayDevice.cpp | 23 +++++++++++- services/surfaceflinger/DisplayDevice.h | 16 ++++++++- services/surfaceflinger/RenderArea.h | 1 + .../surfaceflinger/RenderEngine/Description.cpp | 4 +++ services/surfaceflinger/RenderEngine/Description.h | 3 ++ .../RenderEngine/GLES20RenderEngine.cpp | 4 +++ .../RenderEngine/GLES20RenderEngine.h | 23 ++++++------ services/surfaceflinger/RenderEngine/Program.cpp | 4 +++ services/surfaceflinger/RenderEngine/Program.h | 3 ++ .../surfaceflinger/RenderEngine/ProgramCache.cpp | 6 +++- .../surfaceflinger/RenderEngine/RenderEngine.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 41 ++++++++-------------- .../unittests/mock/RenderEngine/MockRenderEngine.h | 1 + 14 files changed, 91 insertions(+), 42 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp index 50f9bf13fd..a36911d1cf 100644 --- a/libs/ui/HdrCapabilities.cpp +++ b/libs/ui/HdrCapabilities.cpp @@ -27,7 +27,6 @@ HdrCapabilities::~HdrCapabilities() = default; HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) = default; HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) = default; - size_t HdrCapabilities::getFlattenedSize() const { return sizeof(mMaxLuminance) + sizeof(mMaxAverageLuminance) + diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 7c6302e70a..00f8cc9c5c 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -108,7 +108,8 @@ DisplayDevice::DisplayDevice( mSupportedPerFrameMetadata(supportedPerFrameMetadata) { // clang-format on - for (Hdr hdrType : hdrCapabilities.getSupportedHdrTypes()) { + std::vector types = hdrCapabilities.getSupportedHdrTypes(); + for (Hdr hdrType : types) { switch (hdrType) { case Hdr::HDR10: mHasHdr10 = true; @@ -124,6 +125,26 @@ DisplayDevice::DisplayDevice( } } + float minLuminance = hdrCapabilities.getDesiredMinLuminance(); + float maxLuminance = hdrCapabilities.getDesiredMaxLuminance(); + float maxAverageLuminance = hdrCapabilities.getDesiredMaxAverageLuminance(); + + minLuminance = minLuminance <= 0.0 ? sDefaultMinLumiance : minLuminance; + maxLuminance = maxLuminance <= 0.0 ? sDefaultMaxLumiance : maxLuminance; + maxAverageLuminance = maxAverageLuminance <= 0.0 ? sDefaultMaxLumiance : maxAverageLuminance; + if (this->hasWideColorGamut()) { + // insert HDR10/HLG as we will force client composition for HDR10/HLG + // layers + if (!hasHDR10Support()) { + types.push_back(Hdr::HDR10); + } + + if (!hasHLGSupport()) { + types.push_back(Hdr::HLG); + } + } + mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance); + // initialize the display orientation transform. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index df5d945405..1df8c49b1f 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,9 @@ class HWComposer; class DisplayDevice : public LightRefBase { public: + constexpr static float sDefaultMinLumiance = 0.0; + constexpr static float sDefaultMaxLumiance = 500.0; + // region in layer-stack space mutable Region dirtyRegion; // region in screen space @@ -141,6 +145,13 @@ public: bool hasHDR10Support() const { return mHasHdr10; } bool hasHLGSupport() const { return mHasHLG; } bool hasDolbyVisionSupport() const { return mHasDolbyVision; } + // The returned HdrCapabilities is the combination of HDR capabilities from + // hardware composer and RenderEngine. When the DisplayDevice supports wide + // color gamut, RenderEngine is able to simulate HDR support in Display P3 + // color space for both PQ and HLG HDR contents. The minimum and maximum + // luminance will be set to sDefaultMinLumiance and sDefaultMaxLumiance + // respectively if hardware composer doesn't return meaningful values. + const HdrCapabilities& getHdrCapabilities() const { return mHdrCapabilities; } void swapBuffers(HWComposer& hwc) const; @@ -261,7 +272,7 @@ private: bool mHasHdr10; bool mHasHLG; bool mHasDolbyVision; - + HdrCapabilities mHdrCapabilities; const int32_t mSupportedPerFrameMetadata; }; @@ -309,6 +320,9 @@ public: ui::Dataspace getDataSpace() const override { return mDevice->getCompositionDataSpace(); } + float getDisplayMaxLuminance() const override { + return mDevice->getHdrCapabilities().getDesiredMaxLuminance(); + } private: const sp mDevice; diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 36306773f7..4694403c2d 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -32,6 +32,7 @@ public: virtual Rect getSourceCrop() const = 0; virtual bool getWideColorSupport() const = 0; virtual ui::Dataspace getDataSpace() const = 0; + virtual float getDisplayMaxLuminance() const = 0; virtual void render(std::function drawLayers) { drawLayers(); } diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp index 323bdb2b41..0ccdbc4364 100644 --- a/services/surfaceflinger/RenderEngine/Description.cpp +++ b/services/surfaceflinger/RenderEngine/Description.cpp @@ -73,4 +73,8 @@ void Description::setOutputTransferFunction(TransferFunction transferFunction) { mOutputTransferFunction = transferFunction; } +void Description::setDisplayMaxLuminance(const float maxLuminance) { + mDisplayMaxLuminance = maxLuminance; +} + } /* namespace android */ diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h index 5854ba49d1..b09e3a88ab 100644 --- a/services/surfaceflinger/RenderEngine/Description.h +++ b/services/surfaceflinger/RenderEngine/Description.h @@ -55,6 +55,7 @@ public: }; void setInputTransferFunction(TransferFunction transferFunction); void setOutputTransferFunction(TransferFunction transferFunction); + void setDisplayMaxLuminance(const float maxLuminance); private: friend class Program; @@ -83,6 +84,8 @@ private: // transfer functions for the input/output TransferFunction mInputTransferFunction = TransferFunction::LINEAR; TransferFunction mOutputTransferFunction = TransferFunction::LINEAR; + + float mDisplayMaxLuminance; }; } /* namespace android */ diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 6e0fa329f1..8e3c837dd7 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -224,6 +224,10 @@ void GLES20RenderEngine::setOutputDataSpace(Dataspace dataspace) { mOutputDataSpace = dataspace; } +void GLES20RenderEngine::setDisplayMaxLuminance(const float maxLuminance) { + mState.setDisplayMaxLuminance(maxLuminance); +} + void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) { GLuint target = texture.getTextureTarget(); glBindTexture(target, texture.getTextureName()); diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index 99da19d6b1..7177aad032 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -75,17 +75,7 @@ protected: void setSourceY410BT2020(bool enable) override; void setSourceDataSpace(ui::Dataspace source) override; void setOutputDataSpace(ui::Dataspace dataspace) override; - - // Current dataspace of layer being rendered - ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN; - - // Current output dataspace of the render engine - ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN; - - // Currently only supporting sRGB, BT2020 and DisplayP3 color spaces - const bool mPlatformHasWideColor = false; - mat4 mSrgbToDisplayP3; - mat4 mBt2020ToDisplayP3; + void setDisplayMaxLuminance(const float maxLuminance) override; virtual void setupLayerTexturing(const Texture& texture); virtual void setupLayerBlackedOut(); @@ -98,6 +88,17 @@ protected: virtual size_t getMaxTextureSize() const; virtual size_t getMaxViewportDims() const; + + // Current dataspace of layer being rendered + ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN; + + // Current output dataspace of the render engine + ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN; + + // Currently only supporting sRGB, BT2020 and DisplayP3 color spaces + const bool mPlatformHasWideColor = false; + mat4 mSrgbToDisplayP3; + mat4 mBt2020ToDisplayP3; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp index 225bcf0327..e5261c28f7 100644 --- a/services/surfaceflinger/RenderEngine/Program.cpp +++ b/services/surfaceflinger/RenderEngine/Program.cpp @@ -64,6 +64,7 @@ Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const c mTextureMatrixLoc = glGetUniformLocation(programId, "texture"); mSamplerLoc = glGetUniformLocation(programId, "sampler"); mColorLoc = glGetUniformLocation(programId, "color"); + mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance"); // set-up the default values for our uniforms glUseProgram(programId); @@ -136,6 +137,9 @@ void Program::setUniforms(const Description& desc) { if (mColorMatrixLoc >= 0) { glUniformMatrix4fv(mColorMatrixLoc, 1, GL_FALSE, desc.mColorMatrix.asArray()); } + if (mDisplayMaxLuminanceLoc >= 0) { + glUniform1f(mDisplayMaxLuminanceLoc, desc.mDisplayMaxLuminance); + } // these uniforms are always present glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray()); } diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/Program.h index 6e57fdd56f..55b9cdd93b 100644 --- a/services/surfaceflinger/RenderEngine/Program.h +++ b/services/surfaceflinger/RenderEngine/Program.h @@ -80,6 +80,9 @@ private: /* location of the color uniform */ GLint mColorLoc; + + /* location of display luminance uniform */ + GLint mDisplayMaxLuminanceLoc; }; } /* namespace android */ diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index fb63296de3..5d5462f728 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -247,7 +247,7 @@ void ProgramCache::generateOOTF(Formatter& fs, const Key& needs) { const float maxMasteringLumi = 1000.0; const float maxContentLumi = 1000.0; const float maxInLumi = min(maxMasteringLumi, maxContentLumi); - const float maxOutLumi = 500.0; + const float maxOutLumi = displayMaxLuminance; // Calculate Y value in XYZ color space. float colorY = CalculateY(color); @@ -443,6 +443,10 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { if (needs.hasColorMatrix()) { fs << "uniform mat4 colorMatrix;"; + // Currently, only the OOTF of BT2020 PQ needs display maximum luminance. + if (needs.getInputTF() == Key::INPUT_TF_ST2084) { + fs << "uniform float displayMaxLuminance"; + } generateEOTF(fs, needs); generateOOTF(fs, needs); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index f78b230778..df9e6a74a2 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -117,10 +117,11 @@ public: virtual void disableTexturing() = 0; virtual void disableBlending() = 0; - // wide color support + // HDR and wide color gamut support virtual void setSourceY410BT2020(bool enable) = 0; virtual void setSourceDataSpace(ui::Dataspace source) = 0; virtual void setOutputDataSpace(ui::Dataspace dataspace) = 0; + virtual void setDisplayMaxLuminance(const float maxLuminance) = 0; // drawing virtual void drawMesh(const Mesh& mesh) = 0; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e12d7ca73d..f736c8cfda 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1119,31 +1119,14 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp& display, return BAD_VALUE; } - HdrCapabilities capabilities; - int status = getBE().mHwc->getHdrCapabilities( - displayDevice->getHwcDisplayId(), &capabilities); - if (status == NO_ERROR) { - if (displayDevice->hasWideColorGamut()) { - std::vector types = capabilities.getSupportedHdrTypes(); - // insert HDR10/HLG as we will force client composition for HDR10/HLG - // layers - if (!displayDevice->hasHDR10Support()) { - types.push_back(Hdr::HDR10); - } - if (!displayDevice->hasHLGSupport()) { - types.push_back(Hdr::HLG); - } - - *outCapabilities = HdrCapabilities(types, - capabilities.getDesiredMaxLuminance(), - capabilities.getDesiredMaxAverageLuminance(), - capabilities.getDesiredMinLuminance()); - } else { - *outCapabilities = std::move(capabilities); - } - } else { - return BAD_VALUE; - } + // At this point the DisplayDeivce should already be set up, + // meaning the luminance information is already queried from + // hardware composer and stored properly. + const HdrCapabilities& capabilities = displayDevice->getHdrCapabilities(); + *outCapabilities = HdrCapabilities(capabilities.getSupportedHdrTypes(), + capabilities.getDesiredMaxLuminance(), + capabilities.getDesiredMaxAverageLuminance(), + capabilities.getDesiredMinLuminance()); return NO_ERROR; } @@ -2917,6 +2900,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev outputDataspace = displayDevice->getCompositionDataSpace(); } getBE().mRenderEngine->setOutputDataSpace(outputDataspace); + getBE().mRenderEngine->setDisplayMaxLuminance( + displayDevice->getHdrCapabilities().getDesiredMaxLuminance()); if (!displayDevice->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", @@ -4721,6 +4706,9 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, } bool getWideColorSupport() const override { return false; } Dataspace getDataSpace() const override { return Dataspace::UNKNOWN; } + float getDisplayMaxLuminance() const override { + return DisplayDevice::sDefaultMaxLumiance; + } class ReparentForDrawing { public: @@ -4923,7 +4911,8 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, if (renderArea.getWideColorSupport()) { outputDataspace = renderArea.getDataSpace(); } - getBE().mRenderEngine->setOutputDataSpace(outputDataspace); + engine.setOutputDataSpace(outputDataspace); + engine.setDisplayMaxLuminance(renderArea.getDisplayMaxLuminance()); // make sure to clear all GL error flags engine.checkErrors(); diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index 9bb2a3c961..29cd2d545a 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -66,6 +66,7 @@ public: MOCK_METHOD1(setSourceY410BT2020, void(bool)); MOCK_METHOD1(setSourceDataSpace, void(ui::Dataspace)); MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace)); + MOCK_METHOD1(setDisplayMaxLuminance, void(const float)); MOCK_METHOD2(bindNativeBufferAsFrameBuffer, void(ANativeWindowBuffer*, RE::BindNativeBufferAsFramebuffer*)); MOCK_METHOD1(unbindNativeBufferAsFrameBuffer, void(RE::BindNativeBufferAsFramebuffer*)); -- cgit v1.2.3-59-g8ed1b From 0102ad2d522de255efabd50adf6c6a27811344f4 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 2 May 2018 17:37:17 -0700 Subject: SurfaceFlinger TimeStats Metrics Add timestats metrics for SurfaceFlinger. Keep track of global metrics like total frames, missed frames, frames fellback to client compositions, etc, as well as layer timing metrics like the delta combination of postTime, desiredPresentTime, acqureTime, latchTime, presentTime, etc. This metric is aimed at GMScore. Test: dumpsys SurfaceFlinger --timestats [go/sf-timestats for more args] Bug: b/70388650 Change-Id: I6e4545aef62f7893020533a4e7521541ea453ecd Merged-In: I6e4545aef62f7893020533a4e7521541ea453ecd --- services/surfaceflinger/Android.bp | 4 + services/surfaceflinger/BufferLayer.cpp | 17 +- services/surfaceflinger/Layer.cpp | 6 + services/surfaceflinger/Layer.h | 3 + services/surfaceflinger/SurfaceFlinger.cpp | 28 +- services/surfaceflinger/SurfaceFlinger.h | 2 + services/surfaceflinger/TimeStats/TimeStats.cpp | 498 +++++++++++++++++++++ services/surfaceflinger/TimeStats/TimeStats.h | 103 +++++ .../TimeStats/timestatsproto/Android.bp | 55 +++ .../TimeStats/timestatsproto/TimeStatsHelper.cpp | 156 +++++++ .../include/timestatsproto/TimeStatsHelper.h | 72 +++ .../include/timestatsproto/TimeStatsProtoHeader.h | 23 + .../TimeStats/timestatsproto/jarjar-rules.txt | 1 + .../TimeStats/timestatsproto/timestats.proto | 69 +++ services/surfaceflinger/tests/Android.bp | 1 + services/surfaceflinger/tests/fakehwc/Android.bp | 1 + 16 files changed, 1030 insertions(+), 9 deletions(-) create mode 100644 services/surfaceflinger/TimeStats/TimeStats.cpp create mode 100644 services/surfaceflinger/TimeStats/TimeStats.h create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/Android.bp create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsProtoHeader.h create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt create mode 100644 services/surfaceflinger/TimeStats/timestatsproto/timestats.proto (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 5b1e631b4d..6a69844d9f 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -45,6 +45,7 @@ cc_defaults { "libpdx_default_transport", "libprotobuf-cpp-lite", "libsync", + "libtimestats_proto", "libui", "libutils", "libvulkan", @@ -124,6 +125,7 @@ filegroup { "SurfaceFlinger.cpp", "SurfaceInterceptor.cpp", "SurfaceTracing.cpp", + "TimeStats/TimeStats.cpp", "Transform.cpp", ], } @@ -172,6 +174,7 @@ cc_binary { "liblayers_proto", "liblog", "libsurfaceflinger", + "libtimestats_proto", "libutils", ], static_libs: [ @@ -213,5 +216,6 @@ cc_library_shared { subdirs = [ "layerproto", + "TimeStats/timestatsproto", "tests", ] diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 7fd9d01a51..4c3844e130 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -316,6 +316,9 @@ bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFenc nsecs_t desiredPresentTime = mConsumer->getTimestamp(); mFrameTracker.setDesiredPresentTime(desiredPresentTime); + const std::string layerName(getName().c_str()); + mTimeStats.setDesiredTime(layerName, mCurrentFrameNumber, desiredPresentTime); + std::shared_ptr frameReadyFence = mConsumer->getCurrentFenceTime(); if (frameReadyFence->isValid()) { mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); @@ -326,12 +329,15 @@ bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFenc } if (presentFence->isValid()) { + mTimeStats.setPresentFence(layerName, mCurrentFrameNumber, presentFence); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else { // The HWC doesn't support present fences, so use the refresh // timestamp instead. - mFrameTracker.setActualPresentTime( - mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY)); + const nsecs_t actualPresentTime = + mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY); + mTimeStats.setPresentTime(layerName, mCurrentFrameNumber, actualPresentTime); + mFrameTracker.setActualPresentTime(actualPresentTime); } mFrameTracker.advanceFrame(); @@ -441,6 +447,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // and return early if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); + mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); android_atomic_dec(&mQueuedFrames); } @@ -454,6 +461,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime Mutex::Autolock lock(mQueueItemLock); mQueueItems.clear(); android_atomic_and(0, &mQueuedFrames); + mTimeStats.clearLayerRecord(getName().c_str()); } // Once we have hit this state, the shadow queue may no longer @@ -474,10 +482,15 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // Remove any stale buffers that have been dropped during // updateTexImage while (mQueueItems[0].mFrameNumber != currentFrameNumber) { + mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); android_atomic_dec(&mQueuedFrames); } + const std::string layerName(getName().c_str()); + mTimeStats.setAcquireFence(layerName, currentFrameNumber, mQueueItems[0].mFenceTime); + mTimeStats.setLatchTime(layerName, currentFrameNumber, latchTime); + mQueueItems.removeAt(0); } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index bbc974de2f..2802fc7b21 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1532,10 +1532,16 @@ void Layer::dumpFrameEvents(String8& result) { void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); + mTimeStats.onDisconnect(getName().c_str()); } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) { + if (newTimestamps) { + mTimeStats.setPostTime(getName().c_str(), newTimestamps->frameNumber, + newTimestamps->postedTime); + } + Mutex::Autolock lock(mFrameEventHistoryMutex); if (newTimestamps) { // If there are any unsignaled fences in the aquire timeline at this diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index be3967b2cb..0b15b67062 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -41,6 +41,7 @@ #include "LayerVector.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" +#include "TimeStats/TimeStats.h" #include "Transform.h" #include @@ -737,6 +738,8 @@ protected: FenceTimeline mAcquireTimeline; FenceTimeline mReleaseTimeline; + TimeStats& mTimeStats = TimeStats::getInstance(); + // main thread int mActiveBufferSlot; sp mActiveBuffer; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f736c8cfda..e3a47069f8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1470,9 +1470,13 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { Fence::SIGNAL_TIME_PENDING); ATRACE_INT("FrameMissed", static_cast(frameMissed)); if (mPropagateBackpressure && frameMissed) { + mTimeStats.incrementMissedFrames(true); signalLayerUpdate(); break; } + if (frameMissed) { + mTimeStats.incrementMissedFrames(false); + } // Now that we're going to make it to the handleMessageTransaction() // call below it's safe to call updateVrFlinger(), which will @@ -1771,6 +1775,11 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) mAnimFrameTracker.advanceFrame(); } + mTimeStats.incrementTotalFrames(); + if (mHadClientComposition) { + mTimeStats.incrementClientCompositionFrames(); + } + if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && hw->getPowerMode() == HWC_POWER_MODE_OFF) { return; @@ -3824,12 +3833,6 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro size_t index = 0; size_t numArgs = args.size(); - if (asProto) { - LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); - result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); - dumpAll = false; - } - if (numArgs) { if ((index < numArgs) && (args[index] == String16("--list"))) { @@ -3906,10 +3909,21 @@ status_t SurfaceFlinger::doDump(int fd, const Vector& args, bool asPro mLayerStats.dump(result); dumpAll = false; } + + if ((index < numArgs) && (args[index] == String16("--timestats"))) { + index++; + mTimeStats.parseArgs(asProto, args, index, result); + dumpAll = false; + } } if (dumpAll) { - dumpAllLocked(args, index, result); + if (asProto) { + LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); + result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); + } else { + dumpAllLocked(args, index, result); + } } if (locked) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 33706dafe9..a1c8a33674 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -63,6 +63,7 @@ #include "SurfaceInterceptor.h" #include "SurfaceTracing.h" #include "StartPropertySetThread.h" +#include "TimeStats/TimeStats.h" #include "VSyncModulator.h" #include "DisplayHardware/HWC2.h" @@ -815,6 +816,7 @@ private: std::make_unique(this); SurfaceTracing mTracing; LayerStats mLayerStats; + TimeStats& mTimeStats = TimeStats::getInstance(); bool mUseHwcVirtualDisplays = false; // Restrict layers to use two buffers in their bufferqueues. diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp new file mode 100644 index 0000000000..5f2dd32182 --- /dev/null +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -0,0 +1,498 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#undef LOG_TAG +#define LOG_TAG "TimeStats" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "TimeStats.h" + +#include + +#include + +#include +#include + +#include +#include + +namespace android { + +TimeStats& TimeStats::getInstance() { + static std::unique_ptr sInstance; + static std::once_flag sOnceFlag; + + std::call_once(sOnceFlag, [] { sInstance.reset(new TimeStats); }); + return *sInstance.get(); +} + +void TimeStats::parseArgs(bool asProto, const Vector& args, size_t& index, + String8& result) { + ATRACE_CALL(); + + if (args.size() > index + 10) { + ALOGD("Invalid args count"); + return; + } + + std::unordered_map argsMap; + while (index < args.size()) { + argsMap[std::string(String8(args[index]).c_str())] = index; + ++index; + } + + if (argsMap.count("-disable")) { + disable(); + } + + if (argsMap.count("-dump")) { + int64_t maxLayers = 0; + auto iter = argsMap.find("-maxlayers"); + if (iter != argsMap.end() && iter->second + 1 < static_cast(args.size())) { + maxLayers = strtol(String8(args[iter->second + 1]).c_str(), nullptr, 10); + maxLayers = std::clamp(maxLayers, int64_t(0), int64_t(UINT32_MAX)); + } + + dump(asProto, static_cast(maxLayers), result); + } + + if (argsMap.count("-clear")) { + clear(); + } + + if (argsMap.count("-enable")) { + enable(); + } +} + +void TimeStats::incrementTotalFrames() { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + timeStats.totalFrames++; +} + +void TimeStats::incrementMissedFrames(bool propagateBackpressure) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + if (propagateBackpressure) { + timeStats.totalFrames--; + } + timeStats.missedFrames++; +} + +void TimeStats::incrementClientCompositionFrames() { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + timeStats.clientCompositionFrames++; +} + +bool TimeStats::recordReadyLocked(const std::string& layerName, TimeRecord* timeRecord) { + if (!timeRecord->ready) { + ALOGV("[%s]-[%" PRIu64 "]-presentFence is still not received", layerName.c_str(), + timeRecord->frameNumber); + return false; + } + + if (timeRecord->acquireFence != nullptr) { + if (timeRecord->acquireFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + return false; + } + if (timeRecord->acquireFence->getSignalTime() != Fence::SIGNAL_TIME_INVALID) { + timeRecord->acquireTime = timeRecord->acquireFence->getSignalTime(); + timeRecord->acquireFence = nullptr; + } else { + ALOGV("[%s]-[%" PRIu64 "]-acquireFence signal time is invalid", layerName.c_str(), + timeRecord->frameNumber); + } + } + + if (timeRecord->presentFence != nullptr) { + if (timeRecord->presentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + return false; + } + if (timeRecord->presentFence->getSignalTime() != Fence::SIGNAL_TIME_INVALID) { + timeRecord->presentTime = timeRecord->presentFence->getSignalTime(); + timeRecord->presentFence = nullptr; + } else { + ALOGV("[%s]-[%" PRIu64 "]-presentFence signal time invalid", layerName.c_str(), + timeRecord->frameNumber); + } + } + + return true; +} + +static int32_t msBetween(nsecs_t start, nsecs_t end) { + int64_t delta = (end - start) / 1000000; + delta = std::clamp(delta, int64_t(INT32_MIN), int64_t(INT32_MAX)); + return static_cast(delta); +} + +void TimeStats::flushAvailableRecordsToStatsLocked(const std::string& layerName) { + ATRACE_CALL(); + + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; + std::vector& timeRecords = layerRecord.timeRecords; + while (!timeRecords.empty()) { + if (!recordReadyLocked(layerName, &timeRecords[0])) break; + ALOGV("[%s]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerName.c_str(), + timeRecords[0].frameNumber, timeRecords[0].presentTime); + + if (prevTimeRecord.ready) { + if (!timeStats.stats.count(layerName)) { + timeStats.stats[layerName].layerName = layerName; + timeStats.stats[layerName].statsStart = static_cast(std::time(0)); + } + TimeStatsHelper::TimeStatsLayer& timeStatsLayer = timeStats.stats[layerName]; + timeStatsLayer.totalFrames++; + + const int32_t postToPresentMs = + msBetween(timeRecords[0].postTime, timeRecords[0].presentTime); + ALOGV("[%s]-[%" PRIu64 "]-post2present[%d]", layerName.c_str(), + timeRecords[0].frameNumber, postToPresentMs); + timeStatsLayer.deltas["post2present"].insert(postToPresentMs); + + const int32_t acquireToPresentMs = + msBetween(timeRecords[0].acquireTime, timeRecords[0].presentTime); + ALOGV("[%s]-[%" PRIu64 "]-acquire2present[%d]", layerName.c_str(), + timeRecords[0].frameNumber, acquireToPresentMs); + timeStatsLayer.deltas["acquire2present"].insert(acquireToPresentMs); + + const int32_t latchToPresentMs = + msBetween(timeRecords[0].latchTime, timeRecords[0].presentTime); + ALOGV("[%s]-[%" PRIu64 "]-latch2present[%d]", layerName.c_str(), + timeRecords[0].frameNumber, latchToPresentMs); + timeStatsLayer.deltas["latch2present"].insert(latchToPresentMs); + + const int32_t desiredToPresentMs = + msBetween(timeRecords[0].desiredTime, timeRecords[0].presentTime); + ALOGV("[%s]-[%" PRIu64 "]-desired2present[%d]", layerName.c_str(), + timeRecords[0].frameNumber, desiredToPresentMs); + timeStatsLayer.deltas["desired2present"].insert(desiredToPresentMs); + + const int32_t presentToPresentMs = + msBetween(prevTimeRecord.presentTime, timeRecords[0].presentTime); + ALOGV("[%s]-[%" PRIu64 "]-present2present[%d]", layerName.c_str(), + timeRecords[0].frameNumber, presentToPresentMs); + timeStatsLayer.deltas["present2present"].insert(presentToPresentMs); + + timeStats.stats[layerName].statsEnd = static_cast(std::time(0)); + } + prevTimeRecord = timeRecords[0]; + // TODO(zzyiwei): change timeRecords to use std::deque + timeRecords.erase(timeRecords.begin()); + layerRecord.waitData--; + } +} + +static bool layerNameIsValid(const std::string& layerName) { + // This regular expression captures the following layer names for instance: + // 1) StatusBat#0 + // 2) NavigationBar#1 + // 3) com.*#0 + // 4) SurfaceView - com.*#0 + // Using [-\\s\t]+ for the conjunction part between SurfaceView and com.* is + // a bit more robust in case there's a slight change. + // The layer name would only consist of . / $ _ 0-9 a-z A-Z in most cases. + std::regex re("(((SurfaceView[-\\s\\t]+)?com\\.[./$\\w]+)|((Status|Navigation)Bar))#\\d+"); + return std::regex_match(layerName.begin(), layerName.end(), re); +} + +void TimeStats::setPostTime(const std::string& layerName, uint64_t frameNumber, nsecs_t postTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-PostTime[%" PRId64 "]", layerName.c_str(), frameNumber, postTime); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName) && !layerNameIsValid(layerName)) { + return; + } + LayerRecord& layerRecord = timeStatsTracker[layerName]; + if (layerRecord.timeRecords.size() == MAX_NUM_TIME_RECORDS) { + ALOGV("[%s]-timeRecords is already at its maximum size[%zu]", layerName.c_str(), + MAX_NUM_TIME_RECORDS); + // TODO(zzyiwei): if this happens, there must be a present fence missing + // or waitData is not in the correct position. Need to think out a + // reasonable way to recover from this state. + return; + } + // For most media content, the acquireFence is invalid because the buffer is + // ready at the queueBuffer stage. In this case, acquireTime should be given + // a default value as postTime. + TimeRecord timeRecord = { + .frameNumber = frameNumber, + .postTime = postTime, + .acquireTime = postTime, + }; + layerRecord.timeRecords.push_back(timeRecord); + if (layerRecord.waitData < 0 || + layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) + layerRecord.waitData = layerRecord.timeRecords.size() - 1; +} + +void TimeStats::setLatchTime(const std::string& layerName, uint64_t frameNumber, + nsecs_t latchTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerName.c_str(), frameNumber, latchTime); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.latchTime = latchTime; + } +} + +void TimeStats::setDesiredTime(const std::string& layerName, uint64_t frameNumber, + nsecs_t desiredTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerName.c_str(), frameNumber, + desiredTime); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.desiredTime = desiredTime; + } +} + +void TimeStats::setAcquireTime(const std::string& layerName, uint64_t frameNumber, + nsecs_t acquireTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerName.c_str(), frameNumber, + acquireTime); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.acquireTime = acquireTime; + } +} + +void TimeStats::setAcquireFence(const std::string& layerName, uint64_t frameNumber, + const std::shared_ptr& acquireFence) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerName.c_str(), frameNumber, + acquireFence->getSignalTime()); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.acquireFence = acquireFence; + } +} + +void TimeStats::setPresentTime(const std::string& layerName, uint64_t frameNumber, + nsecs_t presentTime) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerName.c_str(), frameNumber, + presentTime); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.presentTime = presentTime; + timeRecord.ready = true; + layerRecord.waitData++; + } + + flushAvailableRecordsToStatsLocked(layerName); +} + +void TimeStats::setPresentFence(const std::string& layerName, uint64_t frameNumber, + const std::shared_ptr& presentFence) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerName.c_str(), frameNumber, + presentFence->getSignalTime()); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData]; + if (timeRecord.frameNumber == frameNumber) { + timeRecord.presentFence = presentFence; + timeRecord.ready = true; + layerRecord.waitData++; + } + + flushAvailableRecordsToStatsLocked(layerName); +} + +void TimeStats::onDisconnect(const std::string& layerName) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-onDisconnect", layerName.c_str()); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + flushAvailableRecordsToStatsLocked(layerName); + timeStatsTracker.erase(layerName); +} + +void TimeStats::clearLayerRecord(const std::string& layerName) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-clearLayerRecord", layerName.c_str()); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + layerRecord.timeRecords.clear(); + layerRecord.prevTimeRecord.ready = false; + layerRecord.waitData = -1; +} + +void TimeStats::removeTimeRecord(const std::string& layerName, uint64_t frameNumber) { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + ALOGV("[%s]-[%" PRIu64 "]-removeTimeRecord", layerName.c_str(), frameNumber); + + std::lock_guard lock(mMutex); + if (!timeStatsTracker.count(layerName)) return; + LayerRecord& layerRecord = timeStatsTracker[layerName]; + size_t removeAt = 0; + for (const TimeRecord& record : layerRecord.timeRecords) { + if (record.frameNumber == frameNumber) break; + removeAt++; + } + if (removeAt == layerRecord.timeRecords.size()) return; + layerRecord.timeRecords.erase(layerRecord.timeRecords.begin() + removeAt); + if (layerRecord.waitData > static_cast(removeAt)) { + --layerRecord.waitData; + } +} + +void TimeStats::enable() { + if (mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + ALOGD("Enabled"); + mEnabled.store(true); + timeStats.statsStart = static_cast(std::time(0)); +} + +void TimeStats::disable() { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + ALOGD("Disabled"); + mEnabled.store(false); + timeStats.statsEnd = static_cast(std::time(0)); +} + +void TimeStats::clear() { + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + ALOGD("Cleared"); + timeStats.dumpStats.clear(); + timeStats.stats.clear(); + timeStats.statsStart = (mEnabled.load() ? static_cast(std::time(0)) : 0); + timeStats.statsEnd = 0; + timeStats.totalFrames = 0; + timeStats.missedFrames = 0; + timeStats.clientCompositionFrames = 0; +} + +bool TimeStats::isEnabled() { + return mEnabled.load(); +} + +void TimeStats::dump(bool asProto, uint32_t maxLayers, String8& result) { + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + if (timeStats.statsStart == 0) { + return; + } + + timeStats.statsEnd = static_cast(std::time(0)); + + // TODO(zzyiwei): refactor dumpStats into TimeStatsHelper + timeStats.dumpStats.clear(); + for (auto& ele : timeStats.stats) { + timeStats.dumpStats.push_back(&ele.second); + } + + std::sort(timeStats.dumpStats.begin(), timeStats.dumpStats.end(), + [](TimeStatsHelper::TimeStatsLayer* const& l, + TimeStatsHelper::TimeStatsLayer* const& r) { + return l->totalFrames > r->totalFrames; + }); + + if (maxLayers != 0 && maxLayers < timeStats.dumpStats.size()) { + timeStats.dumpStats.resize(maxLayers); + } + + if (asProto) { + dumpAsProtoLocked(result); + } else { + dumpAsTextLocked(result); + } +} + +void TimeStats::dumpAsTextLocked(String8& result) { + ALOGD("Dumping TimeStats as text"); + result.append(timeStats.toString().c_str()); + result.append("\n"); +} + +void TimeStats::dumpAsProtoLocked(String8& result) { + ALOGD("Dumping TimeStats as proto"); + SFTimeStatsGlobalProto timeStatsProto = timeStats.toProto(); + result.append(timeStatsProto.SerializeAsString().c_str(), timeStatsProto.ByteSize()); +} + +} // namespace android diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h new file mode 100644 index 0000000000..2410265a0d --- /dev/null +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -0,0 +1,103 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +using namespace android::surfaceflinger; + +namespace android { +class String8; + +class TimeStats { + // TODO(zzyiwei): Bound the timeStatsTracker with weighted LRU + // static const size_t MAX_NUM_LAYER_RECORDS = 200; + static const size_t MAX_NUM_TIME_RECORDS = 64; + + struct TimeRecord { + bool ready = false; + uint64_t frameNumber = 0; + nsecs_t postTime = 0; + nsecs_t latchTime = 0; + nsecs_t acquireTime = 0; + nsecs_t desiredTime = 0; + nsecs_t presentTime = 0; + std::shared_ptr acquireFence; + std::shared_ptr presentFence; + }; + + struct LayerRecord { + // This is the index in timeRecords, at which the timestamps for that + // specific frame are still not fully received. This is not waiting for + // fences to signal, but rather waiting to receive those fences/timestamps. + int32_t waitData = -1; + TimeRecord prevTimeRecord; + std::vector timeRecords; + }; + +public: + static TimeStats& getInstance(); + void parseArgs(bool asProto, const Vector& args, size_t& index, String8& result); + void incrementTotalFrames(); + void incrementMissedFrames(bool propagateBackpressure); + void incrementClientCompositionFrames(); + + void setPostTime(const std::string& layerName, uint64_t frameNumber, nsecs_t postTime); + void setLatchTime(const std::string& layerName, uint64_t frameNumber, nsecs_t latchTime); + void setDesiredTime(const std::string& layerName, uint64_t frameNumber, nsecs_t desiredTime); + void setAcquireTime(const std::string& layerName, uint64_t frameNumber, nsecs_t acquireTime); + void setAcquireFence(const std::string& layerName, uint64_t frameNumber, + const std::shared_ptr& acquireFence); + void setPresentTime(const std::string& layerName, uint64_t frameNumber, nsecs_t presentTime); + void setPresentFence(const std::string& layerName, uint64_t frameNumber, + const std::shared_ptr& presentFence); + void onDisconnect(const std::string& layerName); + void clearLayerRecord(const std::string& layerName); + void removeTimeRecord(const std::string& layerName, uint64_t frameNumber); + +private: + TimeStats() = default; + + bool recordReadyLocked(const std::string& layerName, TimeRecord* timeRecord); + void flushAvailableRecordsToStatsLocked(const std::string& layerName); + + void enable(); + void disable(); + void clear(); + bool isEnabled(); + void dump(bool asProto, uint32_t maxLayer, String8& result); + void dumpAsTextLocked(String8& result); + void dumpAsProtoLocked(String8& result); + + std::atomic mEnabled = false; + std::mutex mMutex; + TimeStatsHelper::TimeStatsGlobal timeStats; + std::unordered_map timeStatsTracker; +}; + +} // namespace android diff --git a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp new file mode 100644 index 0000000000..66aa719381 --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp @@ -0,0 +1,55 @@ +cc_library_shared { + name: "libtimestats_proto", + vendor_available: true, + export_include_dirs: ["include"], + + srcs: [ + "TimeStatsHelper.cpp", + "timestats.proto", + ], + + shared_libs: [ + "android.hardware.graphics.common@1.1", + "libui", + "libprotobuf-cpp-lite", + "libbase", + "liblog", + ], + + proto: { + export_proto_headers: true, + }, + + cppflags: [ + "-Werror", + "-Wno-unused-parameter", + "-Wno-format", + "-Wno-c++98-compat-pedantic", + "-Wno-float-conversion", + "-Wno-disabled-macro-expansion", + "-Wno-float-equal", + "-Wno-sign-conversion", + "-Wno-padded", + "-Wno-old-style-cast", + "-Wno-undef", + ], + +} + +java_library_static { + name: "timestatsprotosnano", + host_supported: true, + proto: { + type: "nano", + }, + srcs: ["*.proto"], + no_framework_libs: true, + target: { + android: { + jarjar_rules: "jarjar-rules.txt", + }, + host: { + static_libs: ["libprotobuf-java-nano"], + }, + }, +} diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp new file mode 100644 index 0000000000..ec0570d619 --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include +#include + +#define HISTOGRAM_SIZE 85 + +using android::base::StringAppendF; +using android::base::StringPrintf; + +namespace android { +namespace surfaceflinger { + +// Time buckets for histogram, the calculated time deltas will be lower bounded +// to the buckets in this array. +static const std::array histogramConfig = + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 36, 38, 40, 42, 44, 46, 48, 50, 54, 58, 62, 66, 70, 74, 78, 82, + 86, 90, 94, 98, 102, 106, 110, 114, 118, 122, 126, 130, 134, 138, 142, 146, 150, + 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000}; + +void TimeStatsHelper::Histogram::insert(int32_t delta) { + if (delta < 0) return; + // std::lower_bound won't work on out of range values + if (delta > histogramConfig[HISTOGRAM_SIZE - 1]) { + hist[histogramConfig[HISTOGRAM_SIZE - 1]]++; + return; + } + auto iter = std::lower_bound(histogramConfig.begin(), histogramConfig.end(), delta); + hist[*iter]++; +} + +float TimeStatsHelper::Histogram::averageTime() { + int64_t ret = 0; + int64_t count = 0; + for (auto ele : hist) { + count += ele.second; + ret += ele.first * ele.second; + } + return static_cast(ret) / count; +} + +std::string TimeStatsHelper::Histogram::toString() { + std::string result; + for (int32_t i = 0; i < HISTOGRAM_SIZE; ++i) { + int32_t bucket = histogramConfig[i]; + int32_t count = (hist.count(bucket) == 0) ? 0 : hist[bucket]; + StringAppendF(&result, "%dms=%d ", bucket, count); + } + result.back() = '\n'; + return result; +} + +static std::string getPackageName(const std::string& layerName) { + // This regular expression captures the following for instance: + // StatusBar in StatusBar#0 + // com.appname in com.appname/com.appname.activity#0 + // com.appname in SurfaceView - com.appname/com.appname.activity#0 + const std::regex re("(?:SurfaceView[-\\s\\t]+)?([^/]+).*#\\d+"); + std::smatch match; + if (std::regex_match(layerName.begin(), layerName.end(), match, re)) { + // There must be a match for group 1 otherwise the whole string is not + // matched and the above will return false + return match[1]; + } + return ""; +} + +std::string TimeStatsHelper::TimeStatsLayer::toString() { + std::string result = ""; + StringAppendF(&result, "layerName = %s\n", layerName.c_str()); + packageName = getPackageName(layerName); + StringAppendF(&result, "packageName = %s\n", packageName.c_str()); + StringAppendF(&result, "statsStart = %lld\n", static_cast(statsStart)); + StringAppendF(&result, "statsEnd = %lld\n", static_cast(statsEnd)); + StringAppendF(&result, "totalFrames= %d\n", totalFrames); + if (deltas.find("present2present") != deltas.end()) { + StringAppendF(&result, "averageFPS = %.3f\n", + 1000.0 / deltas["present2present"].averageTime()); + } + for (auto ele : deltas) { + StringAppendF(&result, "%s histogram is as below:\n", ele.first.c_str()); + StringAppendF(&result, "%s", ele.second.toString().c_str()); + } + + return result; +} + +std::string TimeStatsHelper::TimeStatsGlobal::toString() { + std::string result = "SurfaceFlinger TimeStats:\n"; + StringAppendF(&result, "statsStart = %lld\n", static_cast(statsStart)); + StringAppendF(&result, "statsEnd = %lld\n", static_cast(statsEnd)); + StringAppendF(&result, "totalFrames= %d\n", totalFrames); + StringAppendF(&result, "missedFrames= %d\n", missedFrames); + StringAppendF(&result, "clientCompositionFrames= %d\n", clientCompositionFrames); + StringAppendF(&result, "TimeStats for each layer is as below:\n"); + for (auto ele : dumpStats) { + StringAppendF(&result, "%s", ele->toString().c_str()); + } + + return result; +} + +SFTimeStatsLayerProto TimeStatsHelper::TimeStatsLayer::toProto() { + SFTimeStatsLayerProto layerProto; + layerProto.set_layer_name(layerName); + packageName = getPackageName(layerName); + layerProto.set_package_name(packageName); + layerProto.set_stats_start(statsStart); + layerProto.set_stats_end(statsEnd); + layerProto.set_total_frames(totalFrames); + for (auto ele : deltas) { + SFTimeStatsDeltaProto* deltaProto = layerProto.add_deltas(); + deltaProto->set_delta_name(ele.first); + SFTimeStatsHistogramBucketProto* histProto = deltaProto->add_histograms(); + for (auto histEle : ele.second.hist) { + histProto->set_render_millis(histEle.first); + histProto->set_frame_count(histEle.second); + } + } + return layerProto; +} + +SFTimeStatsGlobalProto TimeStatsHelper::TimeStatsGlobal::toProto() { + SFTimeStatsGlobalProto globalProto; + globalProto.set_stats_start(statsStart); + globalProto.set_stats_end(statsEnd); + globalProto.set_total_frames(totalFrames); + globalProto.set_missed_frames(missedFrames); + globalProto.set_client_composition_frames(clientCompositionFrames); + for (auto ele : dumpStats) { + SFTimeStatsLayerProto* layerProto = globalProto.add_stats(); + layerProto->CopyFrom(ele->toProto()); + } + return globalProto; +} + +} // namespace surfaceflinger +} // namespace android diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h new file mode 100644 index 0000000000..c876f21404 --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include + +#include + +#include +#include +#include +#include + +namespace android { +namespace surfaceflinger { + +class TimeStatsHelper { +public: + class Histogram { + public: + // Key is the delta time between timestamps + // Value is the number of appearances of that delta + std::unordered_map hist; + + void insert(int32_t delta); + float averageTime(); + std::string toString(); + }; + + class TimeStatsLayer { + public: + std::string layerName; + std::string packageName; + int64_t statsStart = 0; + int64_t statsEnd = 0; + int32_t totalFrames = 0; + std::unordered_map deltas; + + std::string toString(); + SFTimeStatsLayerProto toProto(); + }; + + class TimeStatsGlobal { + public: + int64_t statsStart = 0; + int64_t statsEnd = 0; + int32_t totalFrames = 0; + int32_t missedFrames = 0; + int32_t clientCompositionFrames = 0; + std::unordered_map stats; + std::vector dumpStats; + + std::string toString(); + SFTimeStatsGlobalProto toProto(); + }; +}; + +} // namespace surfaceflinger +} // namespace android diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsProtoHeader.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsProtoHeader.h new file mode 100644 index 0000000000..fe0d150c3b --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsProtoHeader.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Projectlayerproto/LayerProtoHeader.h + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// pragma is used here to disable the warnings emitted from the protobuf +// headers. By adding #pragma before including layer.pb.h, it supresses +// protobuf warnings, but allows the rest of the files to continuing using +// the current flags. +// This file should be included instead of directly including layer.b.h +#pragma GCC system_header +#include diff --git a/services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt b/services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt new file mode 100644 index 0000000000..40043a861c --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/jarjar-rules.txt @@ -0,0 +1 @@ +rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1 diff --git a/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto new file mode 100644 index 0000000000..a8f6fa8ab1 --- /dev/null +++ b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto @@ -0,0 +1,69 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; + +package android.surfaceflinger; + +option optimize_for = LITE_RUNTIME; + +// frameworks/base/core/proto/android/service/sftimestats.proto is based on +// this proto. Please only make valid protobuf changes to these messages, and +// keep the other file in sync with this one. + +message SFTimeStatsGlobalProto { + // The start & end timestamps in UTC as + // milliseconds since January 1, 1970 + optional int64 stats_start = 1; + optional int64 stats_end = 2; + // Total frames + optional int32 total_frames = 3; + // Total missed frames of SurfaceFlinger. + optional int32 missed_frames = 4; + // Total frames fallback to client composition. + optional int32 client_composition_frames = 5; + + repeated SFTimeStatsLayerProto stats = 6; +} + +message SFTimeStatsLayerProto { + // The layer name + optional string layer_name = 1; + // The package name + optional string package_name = 2; + // The start & end timestamps in UTC as + // milliseconds since January 1, 1970 + optional int64 stats_start = 3; + optional int64 stats_end = 4; + // Distinct frame count. + optional int32 total_frames = 5; + + repeated SFTimeStatsDeltaProto deltas = 6; +} + +message SFTimeStatsDeltaProto { + // Name of the time interval + optional string delta_name = 1; + // Histogram of the delta time + repeated SFTimeStatsHistogramBucketProto histograms = 2; +} + +message SFTimeStatsHistogramBucketProto { + // Lower bound of render time in milliseconds. + optional int32 render_millis = 1; + // Number of frames in the bucket. + optional int32 frame_count = 2; +} diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index 7523399dbf..322e8a0fea 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -36,6 +36,7 @@ cc_test { "liblayers_proto", "liblog", "libprotobuf-cpp-full", + "libtimestats_proto", "libui", "libutils", ] diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 00bc621df0..520df2d63f 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -25,6 +25,7 @@ cc_test { "liblog", "libnativewindow", "libsync", + "libtimestats_proto", "libui", "libutils", ], -- cgit v1.2.3-59-g8ed1b From 28f320b443106f1656f9720224f579136dcf0c61 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 3 May 2018 11:02:56 -0700 Subject: surfaceflinger: fix color tranform matrix races The color transform matrices may be updated by the binder threads while being used by the main thread. Protect the matrices with mStateLock, compute the effective matrix when the individual matrices are updated, and copy the effective matrix to mDrawingState during commitTransaction. This commit fixes the race and moves the matrix computation out of the hot path. Bug: 79210409 Test: night light, color correction, boosted Change-Id: Ibdb756b7b66345ffcef3c665652e20b050865f6d --- services/surfaceflinger/SurfaceFlinger.cpp | 82 +++++++++++++++++------------- services/surfaceflinger/SurfaceFlinger.h | 24 +++++---- 2 files changed, 60 insertions(+), 46 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f736c8cfda..01f855b33a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -244,7 +244,6 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag) mPrimaryDispSync("PrimaryDispSync"), mPrimaryHWVsyncEnabled(false), mHWVsyncAvailable(false), - mHasColorMatrix(false), mHasPoweredOff(false), mNumLayers(0), mVrFlingerRequestsDisplay(false), @@ -723,10 +722,13 @@ void SurfaceFlinger::init() { } void SurfaceFlinger::readPersistentProperties() { + Mutex::Autolock _l(mStateLock); + char value[PROPERTY_VALUE_MAX]; property_get("persist.sys.sf.color_saturation", value, "1.0"); mGlobalSaturationFactor = atof(value); + updateColorMatrixLocked(); ALOGV("Saturation is set to %.2f", mGlobalSaturationFactor); property_get("persist.sys.sf.native_mode", value, "0"); @@ -1859,22 +1861,6 @@ void SurfaceFlinger::rebuildLayerStacks() { } } -mat4 SurfaceFlinger::computeSaturationMatrix() const { - if (mGlobalSaturationFactor == 1.0f) { - return mat4(); - } - - // Rec.709 luma coefficients - float3 luminance{0.213f, 0.715f, 0.072f}; - luminance *= 1.0f - mGlobalSaturationFactor; - return mat4( - vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f}, - vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f}, - vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f}, - vec4{0.0f, 0.0f, 0.0f, 1.0f} - ); -} - // Returns a dataspace that fits all visible layers. The returned dataspace // can only be one of // @@ -2000,9 +1986,6 @@ void SurfaceFlinger::setUpHWComposer() { } } - - mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer(); - // Set the per-frame data for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { auto& displayDevice = mDisplays[displayId]; @@ -2011,9 +1994,9 @@ void SurfaceFlinger::setUpHWComposer() { if (hwcId < 0) { continue; } - if (colorMatrix != mPreviousColorMatrix) { - displayDevice->setColorTransform(colorMatrix); - status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix); + if (mDrawingState.colorMatrixChanged) { + displayDevice->setColorTransform(mDrawingState.colorMatrix); + status_t result = getBE().mHwc->setColorTransform(hwcId, mDrawingState.colorMatrix); ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " "display %zd: %d", displayId, result); } @@ -2046,7 +2029,7 @@ void SurfaceFlinger::setUpHWComposer() { } } - mPreviousColorMatrix = colorMatrix; + mDrawingState.colorMatrixChanged = false; for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { auto& displayDevice = mDisplays[displayId]; @@ -2635,6 +2618,9 @@ void SurfaceFlinger::commitTransaction() mAnimCompositionPending = mAnimTransactionPending; mDrawingState = mCurrentState; + // clear the "changed" flags in current state + mCurrentState.colorMatrixChanged = false; + mDrawingState.traverseInZOrder([](Layer* layer) { layer->commitChildList(); }); @@ -2887,9 +2873,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev mat4 legacySrgbSaturationMatrix = mLegacySrgbSaturationMatrix; const bool applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; if (applyColorMatrix) { - mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer(); - oldColorMatrix = getRenderEngine().setupColorTransform(colorMatrix); - legacySrgbSaturationMatrix = colorMatrix * legacySrgbSaturationMatrix; + oldColorMatrix = getRenderEngine().setupColorTransform(mDrawingState.colorMatrix); + legacySrgbSaturationMatrix = mDrawingState.colorMatrix * legacySrgbSaturationMatrix; } if (hasClientComposition) { @@ -4349,6 +4334,30 @@ bool SurfaceFlinger::startDdmConnection() return true; } +void SurfaceFlinger::updateColorMatrixLocked() { + mat4 colorMatrix; + if (mGlobalSaturationFactor != 1.0f) { + // Rec.709 luma coefficients + float3 luminance{0.213f, 0.715f, 0.072f}; + luminance *= 1.0f - mGlobalSaturationFactor; + mat4 saturationMatrix = mat4( + vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f}, + vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f}, + vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f}, + vec4{0.0f, 0.0f, 0.0f, 1.0f} + ); + colorMatrix = mClientColorMatrix * saturationMatrix * mDaltonizer(); + } else { + colorMatrix = mClientColorMatrix * mDaltonizer(); + } + + if (mCurrentState.colorMatrix != colorMatrix) { + mCurrentState.colorMatrix = colorMatrix; + mCurrentState.colorMatrixChanged = true; + setTransactionFlags(eTransactionNeeded); + } +} + status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { switch (code) { case CREATE_CONNECTION: @@ -4483,6 +4492,7 @@ status_t SurfaceFlinger::onTransact( return NO_ERROR; } case 1014: { + Mutex::Autolock _l(mStateLock); // daltonize n = data.readInt32(); switch (n % 10) { @@ -4504,33 +4514,33 @@ status_t SurfaceFlinger::onTransact( } else { mDaltonizer.setMode(ColorBlindnessMode::Simulation); } - invalidateHwcGeometry(); - repaintEverything(); + + updateColorMatrixLocked(); return NO_ERROR; } case 1015: { + Mutex::Autolock _l(mStateLock); // apply a color matrix n = data.readInt32(); if (n) { // color matrix is sent as a column-major mat4 matrix for (size_t i = 0 ; i < 4; i++) { for (size_t j = 0; j < 4; j++) { - mColorMatrix[i][j] = data.readFloat(); + mClientColorMatrix[i][j] = data.readFloat(); } } } else { - mColorMatrix = mat4(); + mClientColorMatrix = mat4(); } // Check that supplied matrix's last row is {0,0,0,1} so we can avoid // the division by w in the fragment shader - float4 lastRow(transpose(mColorMatrix)[3]); + float4 lastRow(transpose(mClientColorMatrix)[3]); if (any(greaterThan(abs(lastRow - float4{0, 0, 0, 1}), float4{1e-4f}))) { ALOGE("The color transform's last row must be (0, 0, 0, 1)"); } - invalidateHwcGeometry(); - repaintEverything(); + updateColorMatrixLocked(); return NO_ERROR; } // This is an experimental interface @@ -4573,10 +4583,10 @@ status_t SurfaceFlinger::onTransact( return NO_ERROR; } case 1022: { // Set saturation boost + Mutex::Autolock _l(mStateLock); mGlobalSaturationFactor = std::max(0.0f, std::min(data.readFloat(), 2.0f)); - invalidateHwcGeometry(); - repaintEverything(); + updateColorMatrixLocked(); return NO_ERROR; } case 1023: { // Set native mode diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 33706dafe9..9033becf06 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -372,6 +372,10 @@ private: // always uses the Drawing StateSet. layersSortedByZ = other.layersSortedByZ; displays = other.displays; + colorMatrixChanged = other.colorMatrixChanged; + if (colorMatrixChanged) { + colorMatrix = other.colorMatrix; + } return *this; } @@ -379,6 +383,9 @@ private: LayerVector layersSortedByZ; DefaultKeyedVector< wp, DisplayDeviceState> displays; + bool colorMatrixChanged = true; + mat4 colorMatrix; + void traverseInZOrder(const LayerVector::Visitor& visitor) const; void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const; }; @@ -652,8 +659,6 @@ private: ui::ColorMode* outMode, ui::Dataspace* outDataSpace) const; - mat4 computeSaturationMatrix() const; - void setUpHWComposer(); void doComposition(); void doDebugFlashRegions(); @@ -740,6 +745,8 @@ private: // Check to see if we should handoff to vr flinger. void updateVrFlinger(); + void updateColorMatrixLocked(); + /* ------------------------------------------------------------------------ * Attributes */ @@ -753,6 +760,11 @@ private: bool mAnimTransactionPending; SortedVector< sp > mLayersPendingRemoval; + // global color transform states + Daltonizer mDaltonizer; + float mGlobalSaturationFactor = 1.0f; + mat4 mClientColorMatrix; + // Can't be unordered_set because wp<> isn't hashable std::set> mGraphicBufferProducerList; size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS; @@ -842,12 +854,6 @@ private: bool mInjectVSyncs; - Daltonizer mDaltonizer; - - mat4 mPreviousColorMatrix; - mat4 mColorMatrix; - bool mHasColorMatrix; - // Static screen stats bool mHasPoweredOff; @@ -865,8 +871,6 @@ private: DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::MANAGED; // Applied on sRGB layers when the render intent is non-colorimetric. mat4 mLegacySrgbSaturationMatrix; - // Applied globally. - float mGlobalSaturationFactor = 1.0f; bool mBuiltinDisplaySupportsEnhance = false; using CreateBufferQueueFunction = -- cgit v1.2.3-59-g8ed1b From 1148147c4c06d9d5390c7b7c8b0ca5e0c245fc4a Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 4 May 2018 10:43:19 -0700 Subject: surfaceflinger: re-saturate all legacy dataspaces We changed HIDL interface to re-saturate any legacy dataspace. Update SurfaceFlinger to match the behavior. Bug: 78303195 Test: videos are re-saturated as well in GPU fallback Change-Id: Idfa74783061a62d79ca5d9f38e50f4095ce38322 --- services/surfaceflinger/BufferLayer.cpp | 21 +++++++++++++-------- services/surfaceflinger/Layer.cpp | 7 ++++--- services/surfaceflinger/Layer.h | 4 ++-- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- 4 files changed, 20 insertions(+), 14 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 4c3844e130..6feec53257 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -528,11 +528,9 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime recomputeVisibleRegions = true; } - // Dataspace::V0_SRGB and Dataspace::V0_SRGB_LINEAR are not legacy - // data space, however since framework doesn't distinguish them out of - // legacy SRGB, we have to treat them as the same for now. - // UNKNOWN is treated as legacy SRGB when the connected api is EGL. ui::Dataspace dataSpace = mConsumer->getCurrentDataSpace(); + // treat modern dataspaces as legacy dataspaces whenever possible, until + // we can trust the buffer producers switch (dataSpace) { case ui::Dataspace::V0_SRGB: dataSpace = ui::Dataspace::SRGB; @@ -540,10 +538,17 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime case ui::Dataspace::V0_SRGB_LINEAR: dataSpace = ui::Dataspace::SRGB_LINEAR; break; - case ui::Dataspace::UNKNOWN: - if (mConsumer->getCurrentApi() == NATIVE_WINDOW_API_EGL) { - dataSpace = ui::Dataspace::SRGB; - } + case ui::Dataspace::V0_JFIF: + dataSpace = ui::Dataspace::JFIF; + break; + case ui::Dataspace::V0_BT601_625: + dataSpace = ui::Dataspace::BT601_625; + break; + case ui::Dataspace::V0_BT601_525: + dataSpace = ui::Dataspace::BT601_525; + break; + case ui::Dataspace::V0_BT709: + dataSpace = ui::Dataspace::BT709; break; default: break; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2802fc7b21..9043234132 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1650,9 +1650,10 @@ bool Layer::detachChildren() { return true; } -bool Layer::isLegacySrgbDataSpace() const { - return mDrawingState.dataSpace == ui::Dataspace::SRGB || - mDrawingState.dataSpace == ui::Dataspace::SRGB_LINEAR; +bool Layer::isLegacyDataSpace() const { + // return true when no higher bits are set + return !(mDrawingState.dataSpace & (ui::Dataspace::STANDARD_MASK | + ui::Dataspace::TRANSFER_MASK | ui::Dataspace::RANGE_MASK)); } void Layer::setParent(const sp& layer) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 0b15b67062..632efbe23e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -303,8 +303,8 @@ public: // desaturated in order to match what they appears like visually. // With color management, these contents will appear desaturated, thus // needed to be saturated so that they match what they are designed for - // visually. When returns true, legacy SRGB data space is passed to HWC. - bool isLegacySrgbDataSpace() const; + // visually. + bool isLegacyDataSpace() const; // If we have received a new buffer this frame, we will pass its surface // damage down to hardware composer. Otherwise, we must send a region with diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cdf7ccaacc..da6447624c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2989,7 +2989,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev bool restore = false; mat4 savedMatrix; if (mDisplayColorSetting == DisplayColorSetting::ENHANCED && - layer->isLegacySrgbDataSpace()) { + layer->isLegacyDataSpace()) { savedMatrix = getRenderEngine().setupColorTransform(legacySrgbSaturationMatrix); restore = true; -- cgit v1.2.3-59-g8ed1b From 5e9a43e006a185fa43409c7fdb6c32d5bb786e70 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 3 May 2018 14:27:39 -0700 Subject: surfaceflinger: remove hwcId < 0 path in doComposeSurfaces Remove the check for hwcId and re-indent the code. hwcId is never less than zero. Even if it did, getCompositionType(DISPLAY_ID_INVALID) would return HWC2::Composition::Client and it would still work. The motivation is that the hwcId < 0 path has gone outdated since the introduction of legacy sRGB saturation matrix. Bug: 78891890 Test: virtual displays Change-Id: I6f3e779bc0f8ef21d33ce7de49ddbfa95757e473 --- services/surfaceflinger/SurfaceFlinger.cpp | 96 +++++++++++++----------------- 1 file changed, 42 insertions(+), 54 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index da6447624c..88262fb32b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2958,65 +2958,53 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev ALOGV("Rendering client layers"); const Transform& displayTransform = displayDevice->getTransform(); - if (hwcId >= 0) { - // we're using h/w composer - bool firstLayer = true; - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - const Region clip(bounds.intersect( - displayTransform.transform(layer->visibleRegion))); - ALOGV("Layer: %s", layer->getName().string()); - ALOGV(" Composition type: %s", - to_string(layer->getCompositionType(hwcId)).c_str()); - if (!clip.isEmpty()) { - switch (layer->getCompositionType(hwcId)) { - case HWC2::Composition::Cursor: - case HWC2::Composition::Device: - case HWC2::Composition::Sideband: - case HWC2::Composition::SolidColor: { - const Layer::State& state(layer->getDrawingState()); - if (layer->getClearClientTarget(hwcId) && !firstLayer && - layer->isOpaque(state) && (state.color.a == 1.0f) - && hasClientComposition) { - // never clear the very first layer since we're - // guaranteed the FB is already cleared - layer->clearWithOpenGL(renderArea); - } - break; + bool firstLayer = true; + for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + const Region clip(bounds.intersect( + displayTransform.transform(layer->visibleRegion))); + ALOGV("Layer: %s", layer->getName().string()); + ALOGV(" Composition type: %s", + to_string(layer->getCompositionType(hwcId)).c_str()); + if (!clip.isEmpty()) { + switch (layer->getCompositionType(hwcId)) { + case HWC2::Composition::Cursor: + case HWC2::Composition::Device: + case HWC2::Composition::Sideband: + case HWC2::Composition::SolidColor: { + const Layer::State& state(layer->getDrawingState()); + if (layer->getClearClientTarget(hwcId) && !firstLayer && + layer->isOpaque(state) && (state.color.a == 1.0f) + && hasClientComposition) { + // never clear the very first layer since we're + // guaranteed the FB is already cleared + layer->clearWithOpenGL(renderArea); } - case HWC2::Composition::Client: { - // Only apply saturation matrix layer that is legacy SRGB dataspace - // when auto color mode is on. - bool restore = false; - mat4 savedMatrix; - if (mDisplayColorSetting == DisplayColorSetting::ENHANCED && - layer->isLegacyDataSpace()) { - savedMatrix = - getRenderEngine().setupColorTransform(legacySrgbSaturationMatrix); - restore = true; - } - layer->draw(renderArea, clip); - if (restore) { - getRenderEngine().setupColorTransform(savedMatrix); - } - break; + break; + } + case HWC2::Composition::Client: { + // Only apply saturation matrix layer that is legacy SRGB dataspace + // when auto color mode is on. + bool restore = false; + mat4 savedMatrix; + if (mDisplayColorSetting == DisplayColorSetting::ENHANCED && + layer->isLegacyDataSpace()) { + savedMatrix = + getRenderEngine().setupColorTransform(legacySrgbSaturationMatrix); + restore = true; } - default: - break; + layer->draw(renderArea, clip); + if (restore) { + getRenderEngine().setupColorTransform(savedMatrix); + } + break; } - } else { - ALOGV(" Skipping for empty clip"); - } - firstLayer = false; - } - } else { - // we're not using h/w composer - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - const Region clip(bounds.intersect( - displayTransform.transform(layer->visibleRegion))); - if (!clip.isEmpty()) { - layer->draw(renderArea, clip); + default: + break; } + } else { + ALOGV(" Skipping for empty clip"); } + firstLayer = false; } if (applyColorMatrix) { -- cgit v1.2.3-59-g8ed1b From 8e50e696caf054c2f014162834916a8926a194c7 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 4 May 2018 10:12:37 -0700 Subject: surfaceflinger: switch RE color matrices lazily Client composition in doComposeSurfaces normally needs to handle N sRGB layers, when in ColorMode::SRGB N P3 layer and then M sRGB layers, when in ColorMode::DISPLAY_P3 Constantly switching and restoring RE color matrices when handling sRGB layers is less efficient. Do the switches lazily. We don't really care about the current RE color matrix when doComposeSurfaces is called, and we already assume it to be identity. Update RenderEngine::setupColorTransform not to return the current color matrix. Bug: 78891890 Test: night light under Boosted/Enhanced and sRGB/P3 Change-Id: I3b785c2a05f2e1679e486ab2497fc0e13993a791 --- .../RenderEngine/GLES20RenderEngine.cpp | 4 +- .../RenderEngine/GLES20RenderEngine.h | 2 +- .../surfaceflinger/RenderEngine/RenderEngine.h | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 61 +++++++++++++--------- .../unittests/mock/RenderEngine/MockRenderEngine.h | 2 +- 5 files changed, 42 insertions(+), 31 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 08cd5b0012..64095ddfb8 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -259,10 +259,8 @@ void GLES20RenderEngine::setupLayerBlackedOut() { mState.setTexture(texture); } -mat4 GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) { - mat4 oldTransform = mState.getColorMatrix(); +void GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) { mState.setColorMatrix(colorTransform); - return oldTransform; } void GLES20RenderEngine::disableTexturing() { diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index 9acd79bf71..c9e402de8c 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -80,7 +80,7 @@ protected: virtual void setupLayerTexturing(const Texture& texture); virtual void setupLayerBlackedOut(); virtual void setupFillWithColor(float r, float g, float b, float a); - virtual mat4 setupColorTransform(const mat4& colorTransform); + virtual void setupColorTransform(const mat4& colorTransform); virtual void disableTexturing(); virtual void disableBlending(); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index df9e6a74a2..d559464eb5 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -112,7 +112,7 @@ public: virtual void setupLayerBlackedOut() = 0; virtual void setupFillWithColor(float r, float g, float b, float a) = 0; - virtual mat4 setupColorTransform(const mat4& /* colorTransform */) = 0; + virtual void setupColorTransform(const mat4& /* colorTransform */) = 0; virtual void disableTexturing() = 0; virtual void disableBlending() = 0; @@ -224,7 +224,7 @@ public: void checkErrors() const override; - mat4 setupColorTransform(const mat4& /* colorTransform */) override { return mat4(); } + void setupColorTransform(const mat4& /* colorTransform */) override {} // internal to RenderEngine EGLDisplay getEGLDisplay() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 88262fb32b..7a4bc2aa60 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2873,18 +2873,13 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev const DisplayRenderArea renderArea(displayDevice); const auto hwcId = displayDevice->getHwcDisplayId(); const bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId); - const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId); - const bool skipClientColorTransform = getBE().mHwc->hasCapability( - HWC2::Capability::SkipClientColorTransform); ATRACE_INT("hasClientComposition", hasClientComposition); - mat4 oldColorMatrix; - mat4 legacySrgbSaturationMatrix = mLegacySrgbSaturationMatrix; - const bool applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; - if (applyColorMatrix) { - oldColorMatrix = getRenderEngine().setupColorTransform(mDrawingState.colorMatrix); - legacySrgbSaturationMatrix = mDrawingState.colorMatrix * legacySrgbSaturationMatrix; - } + bool applyColorMatrix = false; + bool applyLegacyColorMatrix = false; + mat4 colorMatrix; + mat4 legacyColorMatrix; + const mat4* currentColorMatrix = nullptr; if (hasClientComposition) { ALOGV("hasClientComposition"); @@ -2897,6 +2892,24 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev getBE().mRenderEngine->setDisplayMaxLuminance( displayDevice->getHdrCapabilities().getDesiredMaxLuminance()); + const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId); + const bool skipClientColorTransform = getBE().mHwc->hasCapability( + HWC2::Capability::SkipClientColorTransform); + + applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; + if (applyColorMatrix) { + colorMatrix = mDrawingState.colorMatrix; + } + + applyLegacyColorMatrix = mDisplayColorSetting == DisplayColorSetting::ENHANCED; + if (applyLegacyColorMatrix) { + if (applyColorMatrix) { + legacyColorMatrix = colorMatrix * mLegacySrgbSaturationMatrix; + } else { + legacyColorMatrix = mLegacySrgbSaturationMatrix; + } + } + if (!displayDevice->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", displayDevice->getDisplayName().string()); @@ -2982,20 +2995,20 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev break; } case HWC2::Composition::Client: { - // Only apply saturation matrix layer that is legacy SRGB dataspace - // when auto color mode is on. - bool restore = false; - mat4 savedMatrix; - if (mDisplayColorSetting == DisplayColorSetting::ENHANCED && - layer->isLegacyDataSpace()) { - savedMatrix = - getRenderEngine().setupColorTransform(legacySrgbSaturationMatrix); - restore = true; + // switch color matrices lazily + if (layer->isLegacyDataSpace()) { + if (applyLegacyColorMatrix && currentColorMatrix != &legacyColorMatrix) { + getRenderEngine().setupColorTransform(legacyColorMatrix); + currentColorMatrix = &legacyColorMatrix; + } + } else { + if (applyColorMatrix && currentColorMatrix != &colorMatrix) { + getRenderEngine().setupColorTransform(colorMatrix); + currentColorMatrix = &colorMatrix; + } } + layer->draw(renderArea, clip); - if (restore) { - getRenderEngine().setupColorTransform(savedMatrix); - } break; } default: @@ -3007,8 +3020,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev firstLayer = false; } - if (applyColorMatrix) { - getRenderEngine().setupColorTransform(oldColorMatrix); + if (applyColorMatrix || applyLegacyColorMatrix) { + getRenderEngine().setupColorTransform(mat4()); } // disable scissor at the end of the frame diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index 29cd2d545a..93769a53e4 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -60,7 +60,7 @@ public: MOCK_METHOD1(setupLayerTexturing, void(const Texture&)); MOCK_METHOD0(setupLayerBlackedOut, void()); MOCK_METHOD4(setupFillWithColor, void(float, float, float, float)); - MOCK_METHOD1(setupColorTransform, mat4(const mat4&)); + MOCK_METHOD1(setupColorTransform, void(const mat4&)); MOCK_METHOD0(disableTexturing, void()); MOCK_METHOD0(disableBlending, void()); MOCK_METHOD1(setSourceY410BT2020, void(bool)); -- cgit v1.2.3-59-g8ed1b From 7a28ecb9bdbc1697bdf08804e47a512291e0b878 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 4 May 2018 10:38:39 -0700 Subject: surfaceflinger: no re-saturation when in SRGB mode Under ColorMode::SRGB and RenderIntent::ENHANCE, HWC always applies the legacy sRGB saturation matrix. SurfaceFlinger should not apply the matrix. Bug: 78891890 Test: no color shift when forcing GPU fallback Change-Id: I7ebbefa38c5a6b72d326e0b2d4eee52d8409b5c7 --- services/surfaceflinger/SurfaceFlinger.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7a4bc2aa60..95287d2627 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1873,13 +1873,13 @@ void SurfaceFlinger::rebuildLayerStacks() { // Returns a dataspace that fits all visible layers. The returned dataspace // can only be one of // -// - Dataspace::V0_SRGB +// - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced) // - Dataspace::DISPLAY_P3 // - Dataspace::V0_SCRGB_LINEAR // TODO(b/73825729) Add BT2020 data space. ui::Dataspace SurfaceFlinger::getBestDataspace( const sp& displayDevice) const { - Dataspace bestDataspace = Dataspace::V0_SRGB; + Dataspace bestDataspace = Dataspace::SRGB; for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) { switch (layer->getDataSpace()) { case Dataspace::V0_SCRGB: @@ -1930,7 +1930,7 @@ void SurfaceFlinger::pickColorMode(const sp& displayDevice, break; default: *outMode = ColorMode::SRGB; - *outDataSpace = Dataspace::V0_SRGB; + *outDataSpace = Dataspace::SRGB; break; } } @@ -2901,7 +2901,9 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev colorMatrix = mDrawingState.colorMatrix; } - applyLegacyColorMatrix = mDisplayColorSetting == DisplayColorSetting::ENHANCED; + applyLegacyColorMatrix = (mDisplayColorSetting == DisplayColorSetting::ENHANCED && + outputDataspace != Dataspace::UNKNOWN && + outputDataspace != Dataspace::SRGB); if (applyLegacyColorMatrix) { if (applyColorMatrix) { legacyColorMatrix = colorMatrix * mLegacySrgbSaturationMatrix; -- cgit v1.2.3-59-g8ed1b From 621f9d47638c7a147c6513801eaeb0ed0fdcad30 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 7 May 2018 10:40:55 -0700 Subject: SF TimeStats: fix missed frame logic The current missed frames count is correct, but the decrement on the total frames when mPropagateBackpressure is enabled is not right since the missed frame won't count twice on SurfaceFlinger side. This change fixed this logic error. Test: dumpsys SurfaceFlinger --timestats Bug: b/70388650 Change-Id: I3bab221ad4b9f44da965084fd52da6c82523d1f4 --- services/surfaceflinger/SurfaceFlinger.cpp | 11 +++++------ services/surfaceflinger/TimeStats/TimeStats.cpp | 5 +---- services/surfaceflinger/TimeStats/TimeStats.h | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cdf7ccaacc..2e8a27606a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1471,13 +1471,12 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { (mPreviousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING); ATRACE_INT("FrameMissed", static_cast(frameMissed)); - if (mPropagateBackpressure && frameMissed) { - mTimeStats.incrementMissedFrames(true); - signalLayerUpdate(); - break; - } if (frameMissed) { - mTimeStats.incrementMissedFrames(false); + mTimeStats.incrementMissedFrames(); + if (mPropagateBackpressure) { + signalLayerUpdate(); + break; + } } // Now that we're going to make it to the handleMessageTransaction() diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index 5f2dd32182..a6833a5b5d 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -87,15 +87,12 @@ void TimeStats::incrementTotalFrames() { timeStats.totalFrames++; } -void TimeStats::incrementMissedFrames(bool propagateBackpressure) { +void TimeStats::incrementMissedFrames() { if (!mEnabled.load()) return; ATRACE_CALL(); std::lock_guard lock(mMutex); - if (propagateBackpressure) { - timeStats.totalFrames--; - } timeStats.missedFrames++; } diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index 2410265a0d..f76a62ede0 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -64,7 +64,7 @@ public: static TimeStats& getInstance(); void parseArgs(bool asProto, const Vector& args, size_t& index, String8& result); void incrementTotalFrames(); - void incrementMissedFrames(bool propagateBackpressure); + void incrementMissedFrames(); void incrementClientCompositionFrames(); void setPostTime(const std::string& layerName, uint64_t frameNumber, nsecs_t postTime); -- cgit v1.2.3-59-g8ed1b From d6fa4a70ba70393816176eda0b64e2b576ce6d6b Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 17 Apr 2018 15:09:44 -0700 Subject: [SurfaceFlinger] Add BT2100_PQ and BT2100_HLG color mode. When hardware composer has native HDR10/HLG support, SurfaceFlinger will always pass the layer to hardware composer. When hardware composer doesn't have native HDR10/HLG support, but has BT2100_PQ or BT2100_HLG color mode with render intent, SurfaceFlinger will always set the color mode to BT2100_PQ and BT2100_HLG respectively, and set the render intent to TONE_MAP_ENHANCE if supported, or TONE_MAP_COLORIMETRIC. Otherwise, SurfaceFlinger will set the color mode to Display P3 and simulate PQ/HLG in RenderEngine. Since SurfaceFlinger now can simulate HLG support in Display P3 mode, when apps query HDR capability from platform, we also return HLG support. BUG: 73825729 Test: build, flash Change-Id: I53696360f2b3d986aa9191ff42866e275ba4fd0b Merged-In: I53696360f2b3d986aa9191ff42866e275ba4fd0b --- services/surfaceflinger/DisplayDevice.cpp | 35 +++- services/surfaceflinger/DisplayDevice.h | 20 +++ services/surfaceflinger/SurfaceFlinger.cpp | 188 +++++++++++++++------ services/surfaceflinger/SurfaceFlinger.h | 17 +- .../tests/unittests/DisplayTransactionTest.cpp | 36 +--- .../tests/unittests/TestableSurfaceFlinger.h | 4 +- 6 files changed, 209 insertions(+), 91 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 00f8cc9c5c..2b1e5775ba 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -80,6 +80,7 @@ DisplayDevice::DisplayDevice( bool hasWideColorGamut, const HdrCapabilities& hdrCapabilities, const int32_t supportedPerFrameMetadata, + const std::unordered_map>& hdrAndRenderIntents, int initialPowerMode) : lastCompositionHadVisibleLayers(false), mFlinger(flinger), @@ -105,7 +106,11 @@ DisplayDevice::DisplayDevice( mHasHdr10(false), mHasHLG(false), mHasDolbyVision(false), - mSupportedPerFrameMetadata(supportedPerFrameMetadata) + mSupportedPerFrameMetadata(supportedPerFrameMetadata), + mHasBT2100PQColorimetric(false), + mHasBT2100PQEnhance(false), + mHasBT2100HLGColorimetric(false), + mHasBT2100HLGEnhance(false) { // clang-format on std::vector types = hdrCapabilities.getSupportedHdrTypes(); @@ -145,6 +150,18 @@ DisplayDevice::DisplayDevice( } mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance); + auto iter = hdrAndRenderIntents.find(ColorMode::BT2100_PQ); + if (iter != hdrAndRenderIntents.end()) { + hasToneMapping(iter->second, + &mHasBT2100PQColorimetric, &mHasBT2100PQEnhance); + } + + iter = hdrAndRenderIntents.find(ColorMode::BT2100_HLG); + if (iter != hdrAndRenderIntents.end()) { + hasToneMapping(iter->second, + &mHasBT2100HLGColorimetric, &mHasBT2100HLGEnhance); + } + // initialize the display orientation transform. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); } @@ -529,6 +546,22 @@ void DisplayDevice::dump(String8& result) const { result.append(surfaceDump); } +void DisplayDevice::hasToneMapping(const std::vector& renderIntents, + bool* outColorimetric, bool *outEnhance) { + for (auto intent : renderIntents) { + switch (intent) { + case RenderIntent::TONE_MAP_COLORIMETRIC: + *outColorimetric = true; + break; + case RenderIntent::TONE_MAP_ENHANCE: + *outEnhance = true; + break; + default: + break; + } + } +} + std::atomic DisplayDeviceState::nextDisplayId(1); DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure) diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 1df8c49b1f..d051e33579 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -20,6 +20,7 @@ #include "Transform.h" #include +#include #include @@ -90,6 +91,7 @@ public: bool hasWideColorGamut, const HdrCapabilities& hdrCapabilities, const int32_t supportedPerFrameMetadata, + const std::unordered_map>& hdrAndRenderIntents, int initialPowerMode); // clang-format on @@ -142,6 +144,7 @@ public: status_t beginFrame(bool mustRecompose) const; status_t prepareFrame(HWComposer& hwc); bool hasWideColorGamut() const { return mHasWideColorGamut; } + // Whether h/w composer has native support for specific HDR type. bool hasHDR10Support() const { return mHasHdr10; } bool hasHLGSupport() const { return mHasHLG; } bool hasDolbyVisionSupport() const { return mHasDolbyVision; } @@ -153,6 +156,14 @@ public: // respectively if hardware composer doesn't return meaningful values. const HdrCapabilities& getHdrCapabilities() const { return mHdrCapabilities; } + // Whether h/w composer has BT2100_PQ color mode. + bool hasBT2100PQColorimetricSupport() const { return mHasBT2100PQColorimetric; } + bool hasBT2100PQEnhanceSupport() const { return mHasBT2100PQEnhance; } + + // Whether h/w composer has BT2100_HLG color mode. + bool hasBT2100HLGColorimetricSupport() const { return mHasBT2100HLGColorimetric; } + bool hasBT2100HLGEnhanceSupport() const { return mHasBT2100HLGEnhance; } + void swapBuffers(HWComposer& hwc) const; // called after h/w composer has completed its set() call @@ -203,6 +214,9 @@ public: void dump(String8& result) const; private: + void hasToneMapping(const std::vector& renderIntents, + bool* outColorimetric, bool *outEnhance); + /* * Constants, set during initialization */ @@ -274,6 +288,12 @@ private: bool mHasDolbyVision; HdrCapabilities mHdrCapabilities; const int32_t mSupportedPerFrameMetadata; + // Whether h/w composer has BT2100_PQ and BT2100_HLG color mode with + // colorimetrical tone mapping or enhanced tone mapping. + bool mHasBT2100PQColorimetric; + bool mHasBT2100PQEnhance; + bool mHasBT2100HLGColorimetric; + bool mHasBT2100HLGEnhance; }; struct DisplayDeviceState { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index be70244b79..588d24c45f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1019,27 +1019,13 @@ ColorMode SurfaceFlinger::getActiveColorMode(const sp& display) { } void SurfaceFlinger::setActiveColorModeInternal(const sp& hw, - ColorMode mode, Dataspace dataSpace) { + ColorMode mode, Dataspace dataSpace, + RenderIntent renderIntent) { int32_t type = hw->getDisplayType(); ColorMode currentMode = hw->getActiveColorMode(); Dataspace currentDataSpace = hw->getCompositionDataSpace(); RenderIntent currentRenderIntent = hw->getActiveRenderIntent(); - // Natural Mode means it's color managed and the color must be right, - // thus we pick RenderIntent::COLORIMETRIC as render intent. - // Native Mode means the display is not color managed, and whichever - // render intent is picked doesn't matter, thus return - // RenderIntent::COLORIMETRIC as default here. - RenderIntent renderIntent = RenderIntent::COLORIMETRIC; - - // In Auto Color Mode, we want to strech to panel color space, right now - // only the built-in display supports it. - if (mDisplayColorSetting == DisplayColorSetting::ENHANCED && - mBuiltinDisplaySupportsEnhance && - hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) { - renderIntent = RenderIntent::ENHANCE; - } - if (mode == currentMode && dataSpace == currentDataSpace && renderIntent == currentRenderIntent) { return; @@ -1089,7 +1075,8 @@ status_t SurfaceFlinger::setActiveColorMode(const sp& display, ALOGW("Attempt to set active color mode %s %d for virtual display", decodeColorMode(mMode).c_str(), mMode); } else { - mFlinger.setActiveColorModeInternal(hw, mMode, Dataspace::UNKNOWN); + mFlinger.setActiveColorModeInternal(hw, mMode, Dataspace::UNKNOWN, + RenderIntent::COLORIMETRIC); } return true; } @@ -1869,38 +1856,41 @@ void SurfaceFlinger::rebuildLayerStacks() { } } -// Returns a dataspace that fits all visible layers. The returned dataspace +// Returns a data space that fits all visible layers. The returned data space // can only be one of -// // - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced) // - Dataspace::DISPLAY_P3 // - Dataspace::V0_SCRGB_LINEAR -// TODO(b/73825729) Add BT2020 data space. -ui::Dataspace SurfaceFlinger::getBestDataspace( - const sp& displayDevice) const { - Dataspace bestDataspace = Dataspace::SRGB; +// The returned HDR data space is one of +// - Dataspace::UNKNOWN +// - Dataspace::BT2020_HLG +// - Dataspace::BT2020_PQ +Dataspace SurfaceFlinger::getBestDataspace( + const sp& displayDevice, Dataspace* outHdrDataSpace) const { + Dataspace bestDataSpace = Dataspace::SRGB; + *outHdrDataSpace = Dataspace::UNKNOWN; + for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) { switch (layer->getDataSpace()) { case Dataspace::V0_SCRGB: case Dataspace::V0_SCRGB_LINEAR: - // return immediately - return Dataspace::V0_SCRGB_LINEAR; + bestDataSpace = Dataspace::V0_SCRGB_LINEAR; + break; case Dataspace::DISPLAY_P3: - bestDataspace = Dataspace::DISPLAY_P3; + if (bestDataSpace == Dataspace::SRGB) { + bestDataSpace = Dataspace::DISPLAY_P3; + } break; - // Historically, HDR dataspaces are ignored by SurfaceFlinger. But - // since SurfaceFlinger simulates HDR support now, it should honor - // them unless there is also native support. case Dataspace::BT2020_PQ: case Dataspace::BT2020_ITU_PQ: - if (!displayDevice->hasHDR10Support()) { - return Dataspace::V0_SCRGB_LINEAR; - } + *outHdrDataSpace = Dataspace::BT2020_PQ; break; case Dataspace::BT2020_HLG: case Dataspace::BT2020_ITU_HLG: - if (!displayDevice->hasHLGSupport()) { - return Dataspace::V0_SCRGB_LINEAR; + // When there's mixed PQ content and HLG content, we set the HDR + // data space to be BT2020_PQ and convert HLG to PQ. + if (*outHdrDataSpace == Dataspace::UNKNOWN) { + *outHdrDataSpace = Dataspace::BT2020_HLG; } break; default: @@ -1908,29 +1898,120 @@ ui::Dataspace SurfaceFlinger::getBestDataspace( } } - return bestDataspace; + return bestDataSpace; } // Pick the ColorMode / Dataspace for the display device. -// TODO(b/73825729) Add BT2020 color mode. void SurfaceFlinger::pickColorMode(const sp& displayDevice, - ColorMode* outMode, Dataspace* outDataSpace) const { + ColorMode* outMode, Dataspace* outDataSpace, + RenderIntent* outRenderIntent) const { if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) { *outMode = ColorMode::NATIVE; *outDataSpace = Dataspace::UNKNOWN; + *outRenderIntent = RenderIntent::COLORIMETRIC; return; } - switch (getBestDataspace(displayDevice)) { - case Dataspace::DISPLAY_P3: - case Dataspace::V0_SCRGB_LINEAR: + Dataspace hdrDataSpace; + Dataspace bestDataSpace = getBestDataspace(displayDevice, &hdrDataSpace); + + if (hdrDataSpace == Dataspace::BT2020_PQ) { + // Hardware composer can handle BT2100 ColorMode only when + // - colorimetrical tone mapping is supported, or + // - Auto mode is turned on and enhanced tone mapping is supported. + if (displayDevice->hasBT2100PQColorimetricSupport() || + (mDisplayColorSetting == DisplayColorSetting::ENHANCED && + displayDevice->hasBT2100PQEnhanceSupport())) { + *outMode = ColorMode::BT2100_PQ; + *outDataSpace = Dataspace::BT2020_PQ; + } else if (displayDevice->hasHDR10Support()) { + // Legacy HDR support. HDR layers are treated as UNKNOWN layers. + hdrDataSpace = Dataspace::UNKNOWN; + } else { + // Simulate PQ through RenderEngine, pick DISPLAY_P3 color mode. *outMode = ColorMode::DISPLAY_P3; *outDataSpace = Dataspace::DISPLAY_P3; - break; + } + } else if (hdrDataSpace == Dataspace::BT2020_HLG) { + if (displayDevice->hasBT2100HLGColorimetricSupport() || + (mDisplayColorSetting == DisplayColorSetting::ENHANCED && + displayDevice->hasBT2100HLGEnhanceSupport())) { + *outMode = ColorMode::BT2100_HLG; + *outDataSpace = Dataspace::BT2020_HLG; + } else if (displayDevice->hasHLGSupport()) { + // Legacy HDR support. HDR layers are treated as UNKNOWN layers. + hdrDataSpace = Dataspace::UNKNOWN; + } else { + // Simulate HLG through RenderEngine, pick DISPLAY_P3 color mode. + *outMode = ColorMode::DISPLAY_P3; + *outDataSpace = Dataspace::DISPLAY_P3; + } + } + + // At this point, there's no HDR layer. + if (hdrDataSpace == Dataspace::UNKNOWN) { + switch (bestDataSpace) { + case Dataspace::DISPLAY_P3: + case Dataspace::V0_SCRGB_LINEAR: + *outMode = ColorMode::DISPLAY_P3; + *outDataSpace = Dataspace::DISPLAY_P3; + break; + default: + *outMode = ColorMode::SRGB; + *outDataSpace = Dataspace::SRGB; + break; + } + } + *outRenderIntent = pickRenderIntent(displayDevice, *outMode); +} + +RenderIntent SurfaceFlinger::pickRenderIntent(const sp& displayDevice, + ColorMode colorMode) const { + // Native Mode means the display is not color managed, and whichever + // render intent is picked doesn't matter, thus return + // RenderIntent::COLORIMETRIC as default here. + if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) { + return RenderIntent::COLORIMETRIC; + } + + // In Auto Color Mode, we want to strech to panel color space, right now + // only the built-in display supports it. + if (mDisplayColorSetting == DisplayColorSetting::ENHANCED && + mBuiltinDisplaySupportsEnhance && + displayDevice->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) { + switch (colorMode) { + case ColorMode::DISPLAY_P3: + case ColorMode::SRGB: + return RenderIntent::ENHANCE; + // In Auto Color Mode, BT2100_PQ and BT2100_HLG will only be picked + // when TONE_MAP_ENHANCE or TONE_MAP_COLORIMETRIC is supported. + // If TONE_MAP_ENHANCE is not supported, fall back to TONE_MAP_COLORIMETRIC. + case ColorMode::BT2100_PQ: + return displayDevice->hasBT2100PQEnhanceSupport() ? + RenderIntent::TONE_MAP_ENHANCE : RenderIntent::TONE_MAP_COLORIMETRIC; + case ColorMode::BT2100_HLG: + return displayDevice->hasBT2100HLGEnhanceSupport() ? + RenderIntent::TONE_MAP_ENHANCE : RenderIntent::TONE_MAP_COLORIMETRIC; + // This statement shouldn't be reached, switch cases will always + // cover all possible ColorMode returned by pickColorMode. + default: + return RenderIntent::COLORIMETRIC; + } + } + + // Either enhance is not supported or we are in natural mode. + + // Natural Mode means it's color managed and the color must be right, + // thus we pick RenderIntent::COLORIMETRIC as render intent for non-HDR + // content and pick RenderIntent::TONE_MAP_COLORIMETRIC for HDR content. + switch (colorMode) { + // In Natural Color Mode, BT2100_PQ and BT2100_HLG will only be picked + // when TONE_MAP_COLORIMETRIC is supported. + case ColorMode::BT2100_PQ: + case ColorMode::BT2100_HLG: + return RenderIntent::TONE_MAP_COLORIMETRIC; default: - *outMode = ColorMode::SRGB; - *outDataSpace = Dataspace::SRGB; - break; + return RenderIntent::COLORIMETRIC; } } @@ -2032,8 +2113,9 @@ void SurfaceFlinger::setUpHWComposer() { if (hasWideColorDisplay) { ColorMode colorMode; Dataspace dataSpace; - pickColorMode(displayDevice, &colorMode, &dataSpace); - setActiveColorModeInternal(displayDevice, colorMode, dataSpace); + RenderIntent renderIntent; + pickColorMode(displayDevice, &colorMode, &dataSpace, &renderIntent); + setActiveColorModeInternal(displayDevice, colorMode, dataSpace, renderIntent); } } @@ -2242,6 +2324,8 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( const wp& display, int hwcId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer) { bool hasWideColorGamut = false; + std::unordered_map> hdrAndRenderIntents; + if (hasWideColorDisplay) { std::vector modes = getHwComposer().getColorModes(hwcId); for (ColorMode colorMode : modes) { @@ -2251,7 +2335,6 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( case ColorMode::DCI_P3: hasWideColorGamut = true; break; - // TODO(lpy) Handle BT2020, BT2100_PQ and BT2100_HLG properly. default: break; } @@ -2266,6 +2349,10 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( } } } + + if (colorMode == ColorMode::BT2100_PQ || colorMode == ColorMode::BT2100_HLG) { + hdrAndRenderIntents.emplace(colorMode, renderIntents); + } } } @@ -2305,7 +2392,7 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( dispSurface, std::move(renderSurface), displayWidth, displayHeight, hasWideColorGamut, hdrCapabilities, getHwComposer().getSupportedPerFrameMetadata(hwcId), - initialPowerMode); + hdrAndRenderIntents, initialPowerMode); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); @@ -2317,7 +2404,8 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( defaultColorMode = ColorMode::SRGB; defaultDataSpace = Dataspace::V0_SRGB; } - setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace); + setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace, + RenderIntent::COLORIMETRIC); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); hw->setDisplayName(state.displayName); @@ -2999,6 +3087,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev // switch color matrices lazily if (layer->isLegacyDataSpace()) { if (applyLegacyColorMatrix && currentColorMatrix != &legacyColorMatrix) { + // TODO(b/78891890) Legacy sRGB saturation matrix should be set + // separately. getRenderEngine().setupColorTransform(legacyColorMatrix); currentColorMatrix = &legacyColorMatrix; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 54cf63c950..d9cf9461ca 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -481,7 +481,8 @@ private: // Called on the main thread in response to setActiveColorMode() void setActiveColorModeInternal(const sp& hw, ui::ColorMode colorMode, - ui::Dataspace dataSpace); + ui::Dataspace dataSpace, + ui::RenderIntent renderIntent); // Returns whether the transaction actually modified any state bool handleMessageTransaction(); @@ -653,12 +654,18 @@ private: nsecs_t compositeToPresentLatency); void rebuildLayerStacks(); - // Given a dataSpace, returns the appropriate color_mode to use - // to display that dataSpace. - ui::Dataspace getBestDataspace(const sp& displayDevice) const; + ui::Dataspace getBestDataspace(const sp& displayDevice, + ui::Dataspace* outHdrDataSpace) const; + + // Returns the appropriate ColorMode, Dataspace and RenderIntent for the + // DisplayDevice. The function only returns the supported ColorMode, + // Dataspace and RenderIntent. void pickColorMode(const sp& displayDevice, ui::ColorMode* outMode, - ui::Dataspace* outDataSpace) const; + ui::Dataspace* outDataSpace, + ui::RenderIntent* outRenderIntent) const; + ui::RenderIntent pickRenderIntent(const sp& displayDevice, + ui::ColorMode colorMode) const; void setUpHWComposer(); void doComposition(); diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index bb6ca39023..08da1a2c17 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -47,10 +47,10 @@ using testing::SetArgPointee; using android::hardware::graphics::common::V1_0::Hdr; using android::hardware::graphics::common::V1_1::ColorMode; +using android::hardware::graphics::common::V1_1::RenderIntent; using android::Hwc2::Error; using android::Hwc2::IComposer; using android::Hwc2::IComposerClient; -using android::Hwc2::RenderIntent; using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector; using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; @@ -494,33 +494,6 @@ struct WideColorP3ColorimetricSupportedVariant { } }; -// For this variant, SurfaceFlinger should configure itself with wide color -// display support, and the display should respond with an non-empty list of -// supported color modes. -template -struct WideColorP3EnhanceSupportedVariant { - static constexpr bool WIDE_COLOR_SUPPORTED = true; - - static void injectConfigChange(DisplayTransactionTest* test) { - test->mFlinger.mutableHasWideColorDisplay() = true; - test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::ENHANCED; - } - - static void setupComposerCallExpectations(DisplayTransactionTest* test) { - EXPECT_CALL(*test->mComposer, getColorModes(Display::HWC_DISPLAY_ID, _)) - .WillOnce(DoAll(SetArgPointee<1>(std::vector({ColorMode::DISPLAY_P3})), - Return(Error::NONE))); - EXPECT_CALL(*test->mComposer, - getRenderIntents(Display::HWC_DISPLAY_ID, ColorMode::DISPLAY_P3, _)) - .WillOnce( - DoAll(SetArgPointee<2>(std::vector({RenderIntent::ENHANCE})), - Return(Error::NONE))); - EXPECT_CALL(*test->mComposer, - setColorMode(Display::HWC_DISPLAY_ID, ColorMode::SRGB, RenderIntent::ENHANCE)) - .WillOnce(Return(Error::NONE)); - } -}; - // For this variant, SurfaceFlinger should configure itself with wide display // support, but the display should respond with an empty list of supported color // modes. Wide-color support for the display should not be configured. @@ -638,9 +611,6 @@ using HwcVirtualDisplayCase = using WideColorP3ColorimetricDisplayCase = Case, HdrNotSupportedVariant>; -using WideColorP3EnhanceDisplayCase = - Case, - HdrNotSupportedVariant>; using Hdr10DisplayCase = Case, Hdr10SupportedVariant>; @@ -1043,10 +1013,6 @@ TEST_F(SetupNewDisplayDeviceInternalTest, createWideColorP3Display) { setupNewDisplayDeviceInternalTest(); } -TEST_F(SetupNewDisplayDeviceInternalTest, createWideColorP3EnhanceDisplay) { - setupNewDisplayDeviceInternalTest(); -} - TEST_F(SetupNewDisplayDeviceInternalTest, createHdr10Display) { setupNewDisplayDeviceInternalTest(); } diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index f6895371f6..a4e73613cd 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -289,10 +289,12 @@ public: } sp inject() { + std::unordered_map> hdrAndRenderIntents; sp device = new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, mSecure, mDisplayToken, mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0, - 0, false, HdrCapabilities(), 0, HWC_POWER_MODE_NORMAL); + 0, false, HdrCapabilities(), 0, hdrAndRenderIntents, + HWC_POWER_MODE_NORMAL); mFlinger.mutableDisplays().add(mDisplayToken, device); DisplayDeviceState state(mType, mSecure); -- cgit v1.2.3-59-g8ed1b From 76dd77a6f5298bf0e7cb89ec570ab1578e3947fb Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Wed, 9 May 2018 15:35:33 -0700 Subject: [SurfaceFlinger] Add methods for setting legacy starution matrix. This patch adds methods for setting legacy saturation matrix for legacy sRGB content. Previously it was combined into the color transform matrix which was applied right before applying OETF, however, we want to apply the legacy staturation matrix right after applying EOTF. BUG: 78891890 Test: build Change-Id: I7709eab0857822e48c49237d6681f6e337b4d29e Merged-In: I7709eab0857822e48c49237d6681f6e337b4d29e --- .../surfaceflinger/RenderEngine/Description.cpp | 9 +++++ services/surfaceflinger/RenderEngine/Description.h | 3 ++ .../RenderEngine/GLES20RenderEngine.cpp | 9 +++-- .../RenderEngine/GLES20RenderEngine.h | 1 + services/surfaceflinger/RenderEngine/Program.cpp | 13 +++++-- .../surfaceflinger/RenderEngine/ProgramCache.cpp | 7 ++-- .../surfaceflinger/RenderEngine/RenderEngine.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 40 ++++++++-------------- .../unittests/mock/RenderEngine/MockRenderEngine.h | 1 + 9 files changed, 53 insertions(+), 32 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp index c218e4da50..09414fd56d 100644 --- a/services/surfaceflinger/RenderEngine/Description.cpp +++ b/services/surfaceflinger/RenderEngine/Description.cpp @@ -51,6 +51,10 @@ void Description::setProjectionMatrix(const mat4& mtx) { mProjectionMatrix = mtx; } +void Description::setSaturationMatrix(const mat4& mtx) { + mSaturationMatrix = mtx; +} + void Description::setColorMatrix(const mat4& mtx) { mColorMatrix = mtx; } @@ -78,6 +82,11 @@ bool Description::hasColorMatrix() const { return mColorMatrix != identity; } +bool Description::hasSaturationMatrix() const { + const mat4 identity; + return mSaturationMatrix != identity; +} + const mat4& Description::getColorMatrix() const { return mColorMatrix; } diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h index 6ebb34018d..06eaf35125 100644 --- a/services/surfaceflinger/RenderEngine/Description.h +++ b/services/surfaceflinger/RenderEngine/Description.h @@ -42,12 +42,14 @@ public: void disableTexture(); void setColor(const half4& color); void setProjectionMatrix(const mat4& mtx); + void setSaturationMatrix(const mat4& mtx); void setColorMatrix(const mat4& mtx); void setInputTransformMatrix(const mat3& matrix); void setOutputTransformMatrix(const mat4& matrix); bool hasInputTransformMatrix() const; bool hasOutputTransformMatrix() const; bool hasColorMatrix() const; + bool hasSaturationMatrix() const; const mat4& getColorMatrix() const; void setY410BT2020(bool enable); @@ -90,6 +92,7 @@ private: // projection matrix mat4 mProjectionMatrix; mat4 mColorMatrix; + mat4 mSaturationMatrix; mat3 mInputTransformMatrix; mat4 mOutputTransformMatrix; }; diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 64095ddfb8..aca6c7b805 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -263,6 +263,10 @@ void GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) { mState.setColorMatrix(colorTransform); } +void GLES20RenderEngine::setSaturationMatrix(const mat4& saturationMatrix) { + mState.setSaturationMatrix(saturationMatrix); +} + void GLES20RenderEngine::disableTexturing() { mState.disableTexture(); } @@ -372,10 +376,11 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { // we need to convert the RGB value to linear space and convert it back when: // - there is a color matrix that is not an identity matrix, or + // - there is a saturation matrix that is not an identity matrix, or // - there is an output transform matrix that is not an identity matrix, or // - the input transfer function doesn't match the output transfer function. - if (wideColorState.hasColorMatrix() || wideColorState.hasOutputTransformMatrix() || - inputTransfer != outputTransfer) { + if (wideColorState.hasColorMatrix() || wideColorState.hasSaturationMatrix() || + wideColorState.hasOutputTransformMatrix() || inputTransfer != outputTransfer) { switch (inputTransfer) { case Dataspace::TRANSFER_ST2084: wideColorState.setInputTransferFunction(Description::TransferFunction::ST2084); diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index c9e402de8c..84a48136b0 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -81,6 +81,7 @@ protected: virtual void setupLayerBlackedOut(); virtual void setupFillWithColor(float r, float g, float b, float a); virtual void setupColorTransform(const mat4& colorTransform); + virtual void setSaturationMatrix(const mat4& saturationMatrix); virtual void disableTexturing(); virtual void disableBlending(); diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp index fd2c9688d9..95adaca73b 100644 --- a/services/surfaceflinger/RenderEngine/Program.cpp +++ b/services/surfaceflinger/RenderEngine/Program.cpp @@ -135,13 +135,22 @@ void Program::setUniforms(const Description& desc) { glUniform4fv(mColorLoc, 1, color); } if (mInputTransformMatrixLoc >= 0) { - glUniformMatrix3fv(mInputTransformMatrixLoc, 1, GL_FALSE, - desc.mInputTransformMatrix.asArray()); + // If the input transform matrix is not identity matrix, we want to merge + // the saturation matrix with input transform matrix so that the saturation + // matrix is applied at the correct stage. + mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix) * desc.mSaturationMatrix; + glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray()); } if (mOutputTransformMatrixLoc >= 0) { // The output transform matrix and color matrix can be combined as one matrix // that is applied right before applying OETF. mat4 outputTransformMatrix = desc.mColorMatrix * desc.mOutputTransformMatrix; + // If there is no input transform matrix, we want to merge the saturation + // matrix with output transform matrix to avoid extra matrix multiplication + // in shader. + if (mInputTransformMatrixLoc < 0) { + outputTransformMatrix *= desc.mSaturationMatrix; + } glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE, outputTransformMatrix.asArray()); } diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index abb02905b5..c6c27d50a5 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -129,7 +129,8 @@ ProgramCache::Key ProgramCache::computeKey(const Description& description) { description.hasInputTransformMatrix() ? Key::INPUT_TRANSFORM_MATRIX_ON : Key::INPUT_TRANSFORM_MATRIX_OFF) .set(Key::Key::OUTPUT_TRANSFORM_MATRIX_MASK, - description.hasOutputTransformMatrix() || description.hasColorMatrix() ? + description.hasOutputTransformMatrix() || description.hasColorMatrix() || + (!description.hasInputTransformMatrix() && description.hasSaturationMatrix()) ? Key::OUTPUT_TRANSFORM_MATRIX_ON : Key::OUTPUT_TRANSFORM_MATRIX_OFF); needs.set(Key::Y410_BT2020_MASK, @@ -518,10 +519,10 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { } if (needs.hasInputTransformMatrix()) { - fs << "uniform mat3 inputTransformMatrix;"; + fs << "uniform mat4 inputTransformMatrix;"; fs << R"__SHADER__( highp vec3 InputTransform(const highp vec3 color) { - return inputTransformMatrix * color; + return vec3(inputTransformMatrix * vec4(color, 1.0)); } )__SHADER__"; } else { diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index d559464eb5..a14acaa68d 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -113,6 +113,7 @@ public: virtual void setupFillWithColor(float r, float g, float b, float a) = 0; virtual void setupColorTransform(const mat4& /* colorTransform */) = 0; + virtual void setSaturationMatrix(const mat4& /* saturationMatrix */) = 0; virtual void disableTexturing() = 0; virtual void disableBlending() = 0; @@ -225,6 +226,7 @@ public: void checkErrors() const override; void setupColorTransform(const mat4& /* colorTransform */) override {} + void setSaturationMatrix(const mat4& /* saturationMatrix */) override {} // internal to RenderEngine EGLDisplay getEGLDisplay() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 588d24c45f..c687e9db93 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2963,10 +2963,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev ATRACE_INT("hasClientComposition", hasClientComposition); bool applyColorMatrix = false; - bool applyLegacyColorMatrix = false; - mat4 colorMatrix; - mat4 legacyColorMatrix; - const mat4* currentColorMatrix = nullptr; + bool needsLegacyColorMatrix = false; + bool legacyColorMatrixApplied = false; if (hasClientComposition) { ALOGV("hasClientComposition"); @@ -2985,19 +2983,12 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; if (applyColorMatrix) { - colorMatrix = mDrawingState.colorMatrix; + getRenderEngine().setupColorTransform(mDrawingState.colorMatrix); } - applyLegacyColorMatrix = (mDisplayColorSetting == DisplayColorSetting::ENHANCED && + needsLegacyColorMatrix = (mDisplayColorSetting == DisplayColorSetting::ENHANCED && outputDataspace != Dataspace::UNKNOWN && outputDataspace != Dataspace::SRGB); - if (applyLegacyColorMatrix) { - if (applyColorMatrix) { - legacyColorMatrix = colorMatrix * mLegacySrgbSaturationMatrix; - } else { - legacyColorMatrix = mLegacySrgbSaturationMatrix; - } - } if (!displayDevice->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", @@ -3085,18 +3076,14 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev } case HWC2::Composition::Client: { // switch color matrices lazily - if (layer->isLegacyDataSpace()) { - if (applyLegacyColorMatrix && currentColorMatrix != &legacyColorMatrix) { - // TODO(b/78891890) Legacy sRGB saturation matrix should be set - // separately. - getRenderEngine().setupColorTransform(legacyColorMatrix); - currentColorMatrix = &legacyColorMatrix; - } - } else { - if (applyColorMatrix && currentColorMatrix != &colorMatrix) { - getRenderEngine().setupColorTransform(colorMatrix); - currentColorMatrix = &colorMatrix; + if (layer->isLegacyDataSpace() && needsLegacyColorMatrix) { + if (!legacyColorMatrixApplied) { + getRenderEngine().setSaturationMatrix(mLegacySrgbSaturationMatrix); + legacyColorMatrixApplied = true; } + } else if (legacyColorMatrixApplied) { + getRenderEngine().setSaturationMatrix(mat4()); + legacyColorMatrixApplied = false; } layer->draw(renderArea, clip); @@ -3111,9 +3098,12 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev firstLayer = false; } - if (applyColorMatrix || applyLegacyColorMatrix) { + if (applyColorMatrix) { getRenderEngine().setupColorTransform(mat4()); } + if (needsLegacyColorMatrix && legacyColorMatrixApplied) { + getRenderEngine().setSaturationMatrix(mat4()); + } // disable scissor at the end of the frame getBE().mRenderEngine->disableScissor(); diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index 93769a53e4..ac082933a3 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -61,6 +61,7 @@ public: MOCK_METHOD0(setupLayerBlackedOut, void()); MOCK_METHOD4(setupFillWithColor, void(float, float, float, float)); MOCK_METHOD1(setupColorTransform, void(const mat4&)); + MOCK_METHOD1(setSaturationMatrix, void(const mat4&)); MOCK_METHOD0(disableTexturing, void()); MOCK_METHOD0(disableBlending, void()); MOCK_METHOD1(setSourceY410BT2020, void(bool)); -- cgit v1.2.3-59-g8ed1b From 24b0a485fb58afd16a42de6378c0b743d7aca58a Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Fri, 9 Mar 2018 18:52:26 -0800 Subject: SF: Test coverage for EventThread Add a unit test to cover EventThread.cpp Test: atest libsurfaceflinger_unittest Bug: 74827900 Change-Id: If9479cd9deedff836068cb53e7da2cb64041aea1 --- services/surfaceflinger/EventThread.cpp | 18 +- services/surfaceflinger/EventThread.h | 22 +- services/surfaceflinger/SurfaceFlinger.cpp | 21 +- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/AsyncCallRecorder.h | 165 ++++++++ .../tests/unittests/EventThreadTest.cpp | 422 +++++++++++++++++++++ 6 files changed, 627 insertions(+), 22 deletions(-) create mode 100644 services/surfaceflinger/tests/unittests/AsyncCallRecorder.h create mode 100644 services/surfaceflinger/tests/unittests/EventThreadTest.cpp (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index bb9c0703ed..bc271c8ec5 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -26,14 +26,12 @@ #include #include -#include #include #include #include #include "EventThread.h" -#include "SurfaceFlinger.h" using namespace std::chrono_literals; @@ -47,9 +45,11 @@ EventThread::~EventThread() = default; namespace impl { -EventThread::EventThread(VSyncSource* src, SurfaceFlinger& flinger, bool interceptVSyncs, - const char* threadName) - : mVSyncSource(src), mFlinger(flinger), mInterceptVSyncs(interceptVSyncs) { +EventThread::EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback, + InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName) + : mVSyncSource(src), + mResyncWithRateLimitCallback(resyncWithRateLimitCallback), + mInterceptVSyncsCallback(interceptVSyncsCallback) { for (auto& event : mVSyncEvent) { event.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; event.header.id = 0; @@ -118,7 +118,9 @@ void EventThread::setVsyncRate(uint32_t count, const sp void EventThread::requestNextVsync(const sp& connection) { std::lock_guard lock(mMutex); - mFlinger.resyncWithRateLimit(); + if (mResyncWithRateLimitCallback) { + mResyncWithRateLimitCallback(); + } if (connection->count < 0) { connection->count = 0; @@ -216,8 +218,8 @@ Vector > EventThread::waitForEventLocked( timestamp = mVSyncEvent[i].header.timestamp; if (timestamp) { // we have a vsync event to dispatch - if (mInterceptVSyncs) { - mFlinger.mInterceptor->saveVSyncEvent(timestamp); + if (mInterceptVSyncsCallback) { + mInterceptVSyncsCallback(timestamp); } *event = mVSyncEvent[i]; mVSyncEvent[i].header.timestamp = 0; diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h index 97f0a359e2..9c13ed2755 100644 --- a/services/surfaceflinger/EventThread.h +++ b/services/surfaceflinger/EventThread.h @@ -37,6 +37,7 @@ namespace android { // --------------------------------------------------------------------------- +class EventThreadTest; class SurfaceFlinger; class String8; @@ -82,7 +83,9 @@ class EventThread : public android::EventThread, private VSyncSource::Callback { class Connection : public BnDisplayEventConnection { public: explicit Connection(EventThread* eventThread); - status_t postEvent(const DisplayEventReceiver::Event& event); + virtual ~Connection(); + + virtual status_t postEvent(const DisplayEventReceiver::Event& event); // count >= 1 : continuous event. count is the vsync rate // count == 0 : one-shot event that has not fired @@ -90,7 +93,6 @@ class EventThread : public android::EventThread, private VSyncSource::Callback { int32_t count; private: - virtual ~Connection(); virtual void onFirstRef(); status_t stealReceiveChannel(gui::BitTube* outChannel) override; status_t setVsyncRate(uint32_t count) override; @@ -100,8 +102,11 @@ class EventThread : public android::EventThread, private VSyncSource::Callback { }; public: - EventThread(VSyncSource* src, SurfaceFlinger& flinger, bool interceptVSyncs, - const char* threadName); + using ResyncWithRateLimitCallback = std::function; + using InterceptVSyncsCallback = std::function; + + EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback, + InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName); ~EventThread(); sp createEventConnection() const override; @@ -124,6 +129,8 @@ public: void setPhaseOffset(nsecs_t phaseOffset) override; private: + friend EventThreadTest; + void threadMain(); Vector> waitForEventLocked(std::unique_lock* lock, DisplayEventReceiver::Event* event) @@ -137,8 +144,9 @@ private: void onVSyncEvent(nsecs_t timestamp) override; // constants - VSyncSource* mVSyncSource GUARDED_BY(mMutex) = nullptr; - SurfaceFlinger& mFlinger; + VSyncSource* const mVSyncSource GUARDED_BY(mMutex) = nullptr; + const ResyncWithRateLimitCallback mResyncWithRateLimitCallback; + const InterceptVSyncsCallback mInterceptVSyncsCallback; std::thread mThread; mutable std::mutex mMutex; @@ -155,8 +163,6 @@ private: // for debugging bool mDebugVsyncEnabled GUARDED_BY(mMutex) = false; - - const bool mInterceptVSyncs = false; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 588d24c45f..a837d01d80 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -636,14 +636,21 @@ void SurfaceFlinger::init() { mEventThreadSource = std::make_unique(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app"); - mEventThread = std::make_unique(mEventThreadSource.get(), *this, false, + mEventThread = std::make_unique(mEventThreadSource.get(), + [this]() { resyncWithRateLimit(); }, + impl::EventThread::InterceptVSyncsCallback(), "appEventThread"); mSfEventThreadSource = std::make_unique(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf"); - mSFEventThread = std::make_unique(mSfEventThreadSource.get(), *this, true, - "sfEventThread"); + mSFEventThread = + std::make_unique(mSfEventThreadSource.get(), + [this]() { resyncWithRateLimit(); }, + [this](nsecs_t timestamp) { + mInterceptor->saveVSyncEvent(timestamp); + }, + "sfEventThread"); mEventQueue->setEventThread(mSFEventThread.get()); mVsyncModulator.setEventThread(mSFEventThread.get()); @@ -1132,9 +1139,11 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) { ALOGV("VSync Injections enabled"); if (mVSyncInjector.get() == nullptr) { mVSyncInjector = std::make_unique(); - mInjectorEventThread = - std::make_unique(mVSyncInjector.get(), *this, false, - "injEventThread"); + mInjectorEventThread = std::make_unique< + impl::EventThread>(mVSyncInjector.get(), + [this]() { resyncWithRateLimit(); }, + impl::EventThread::InterceptVSyncsCallback(), + "injEventThread"); } mEventQueue->setEventThread(mInjectorEventThread.get()); } else { diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index bcabe0dffc..3e9f6a425c 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -20,6 +20,7 @@ cc_test { srcs: [ ":libsurfaceflinger_sources", "DisplayTransactionTest.cpp", + "EventThreadTest.cpp", "mock/DisplayHardware/MockComposer.cpp", "mock/DisplayHardware/MockDisplaySurface.cpp", "mock/gui/MockGraphicBufferConsumer.cpp", diff --git a/services/surfaceflinger/tests/unittests/AsyncCallRecorder.h b/services/surfaceflinger/tests/unittests/AsyncCallRecorder.h new file mode 100644 index 0000000000..2245ee1a8a --- /dev/null +++ b/services/surfaceflinger/tests/unittests/AsyncCallRecorder.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace android { + +// This class helps record calls made by another thread when they are made +// asynchronously, with no other way for the tests to verify that the calls have +// been made. +// +// A normal Google Mock recorder, while thread safe, does not allow you to wait +// for asynchronous calls to be made. +// +// Usage: +// +// In the test, use a Google Mock expectation to invoke an instance of the +// recorder: +// +// AsyncCallRecorder recorder; +// +// EXPECT_CALL(someMock, someFunction(_)). +// .WillRepeatedly(Invoke(recorder.getInvocable())); +// +// Then you can invoke the functionality being tested: +// +// threadUnderTest.doSomethingAsync() +// +// And afterwards make a number of assertions using the recorder: +// +// // Wait for one call (with reasonable default timeout), and get the args +// // as a std::tuple inside a std::optional. +// auto args = recorder.waitForCall(); +// // The returned std::optional will have a value if the recorder function +// // was called. +// ASSERT_TRUE(args.has_value()); +// // The arguments can be checked if needed using standard tuple +// // operations. +// EXPECT_EQ(123, std::get<0>(args.value())); +// +// Alternatively maybe you want to assert that a call was not made. +// +// EXPECT_FALSE(recorder.waitForUnexpectedCall().has_value()); +// +// However this check uses a really short timeout so as not to block the test +// unnecessarily. And it could be possible for the check to return false and +// then the recorder could observe a call being made after. +template +class AsyncCallRecorder; + +template +class AsyncCallRecorder { +public: + // For the tests, we expect the wait for an expected change to be signaled + // to be much shorter than this. + static constexpr std::chrono::milliseconds DEFAULT_CALL_EXPECTED_TIMEOUT{10}; + + // The wait here is tricky. We don't expect a change, but we don't want to + // wait forever (or for longer than the typical test function runtime). As + // even the simplest Google Test can take 1ms (1000us) to run, we wait for + // half that time. + static constexpr std::chrono::microseconds UNEXPECTED_CALL_TIMEOUT{500}; + + using ArgTuple = std::tuple>...>; + + void recordCall(Args... args) { + std::lock_guard lock(mMutex); + mCalls.emplace_back(std::make_tuple(args...)); + mCondition.notify_all(); + } + + // Returns a functor which can be used with the Google Mock Invoke() + // function, or as a std::function to record calls. + auto getInvocable() { + return [this](Args... args) { recordCall(args...); }; + } + + // Returns a set of arguments as a std::optional> for the + // oldest call, waiting for the given timeout if necessary if there are no + // arguments in the FIFO. + std::optional waitForCall( + std::chrono::microseconds timeout = DEFAULT_CALL_EXPECTED_TIMEOUT) + NO_THREAD_SAFETY_ANALYSIS { + std::unique_lock lock(mMutex); + + // Wait if necessary for us to have a record from a call. + mCondition.wait_for(lock, timeout, + [this]() NO_THREAD_SAFETY_ANALYSIS { return !mCalls.empty(); }); + + // Return the arguments from the oldest call, if one was made + bool called = !mCalls.empty(); + std::optional result; + if (called) { + result.emplace(std::move(mCalls.front())); + mCalls.pop_front(); + } + return result; + } + + // Waits using a small default timeout for when a call is not expected to be + // made. The returned std::optional> should not have a value + // except if a set of arguments was unexpectedly received because a call was + // actually made. + // + // Note this function uses a small timeout to not block test execution, and + // it is possible the code under test could make the call AFTER the timeout + // expires. + std::optional waitForUnexpectedCall() { return waitForCall(UNEXPECTED_CALL_TIMEOUT); } + +private: + std::mutex mMutex; + std::condition_variable mCondition; + std::deque mCalls GUARDED_BY(mMutex); +}; + +// Like AsyncCallRecorder, but for when the function being invoked +// asynchronously is expected to return a value. +// +// This helper allows a single constant return value to be set to be returned by +// all calls that were made. +template +class AsyncCallRecorderWithCannedReturn; + +template +class AsyncCallRecorderWithCannedReturn + : public AsyncCallRecorder { +public: + explicit AsyncCallRecorderWithCannedReturn(Ret returnvalue) : mReturnValue(returnvalue) {} + + auto getInvocable() { + return [this](Args... args) { + this->recordCall(args...); + return mReturnValue; + }; + } + +private: + const Ret mReturnValue; +}; + +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp new file mode 100644 index 0000000000..80fdb80264 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "LibSurfaceFlingerUnittests" + +#include +#include + +#include + +#include + +#include "AsyncCallRecorder.h" +#include "EventThread.h" + +using namespace std::chrono_literals; +using namespace std::placeholders; + +using testing::_; +using testing::Invoke; + +namespace android { +namespace { + +class MockVSyncSource : public VSyncSource { +public: + MOCK_METHOD1(setVSyncEnabled, void(bool)); + MOCK_METHOD1(setCallback, void(VSyncSource::Callback*)); + MOCK_METHOD1(setPhaseOffset, void(nsecs_t)); +}; + +} // namespace + +class EventThreadTest : public testing::Test { +protected: + class MockEventThreadConnection : public android::impl::EventThread::Connection { + public: + explicit MockEventThreadConnection(android::impl::EventThread* eventThread) + : android::impl::EventThread::Connection(eventThread) {} + MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event)); + }; + + using ConnectionEventRecorder = + AsyncCallRecorderWithCannedReturn; + + EventThreadTest(); + ~EventThreadTest() override; + + void createThread(); + sp createConnection(ConnectionEventRecorder& recorder); + + void expectVSyncSetEnabledCallReceived(bool expectedState); + void expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset); + VSyncSource::Callback* expectVSyncSetCallbackCallReceived(); + void expectInterceptCallReceived(nsecs_t expectedTimestamp); + void expectVsyncEventReceivedByConnection(const char* name, + ConnectionEventRecorder& connectionEventRecorder, + nsecs_t expectedTimestamp, unsigned expectedCount); + void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount); + void expectHotplugEventReceivedByConnection(int expectedDisplayType, bool expectedConnected); + + AsyncCallRecorder mVSyncSetEnabledCallRecorder; + AsyncCallRecorder mVSyncSetCallbackCallRecorder; + AsyncCallRecorder mVSyncSetPhaseOffsetCallRecorder; + AsyncCallRecorder mResyncCallRecorder; + AsyncCallRecorder mInterceptVSyncCallRecorder; + ConnectionEventRecorder mConnectionEventCallRecorder{0}; + + MockVSyncSource mVSyncSource; + std::unique_ptr mThread; + sp mConnection; +}; + +EventThreadTest::EventThreadTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + + EXPECT_CALL(mVSyncSource, setVSyncEnabled(_)) + .WillRepeatedly(Invoke(mVSyncSetEnabledCallRecorder.getInvocable())); + + EXPECT_CALL(mVSyncSource, setCallback(_)) + .WillRepeatedly(Invoke(mVSyncSetCallbackCallRecorder.getInvocable())); + + EXPECT_CALL(mVSyncSource, setPhaseOffset(_)) + .WillRepeatedly(Invoke(mVSyncSetPhaseOffsetCallRecorder.getInvocable())); + + createThread(); + mConnection = createConnection(mConnectionEventCallRecorder); +} + +EventThreadTest::~EventThreadTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); +} + +void EventThreadTest::createThread() { + mThread = + std::make_unique(&mVSyncSource, + mResyncCallRecorder.getInvocable(), + mInterceptVSyncCallRecorder.getInvocable(), + "unit-test-event-thread"); +} + +sp EventThreadTest::createConnection( + ConnectionEventRecorder& recorder) { + sp connection = new MockEventThreadConnection(mThread.get()); + EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable())); + return connection; +} + +void EventThreadTest::expectVSyncSetEnabledCallReceived(bool expectedState) { + auto args = mVSyncSetEnabledCallRecorder.waitForCall(); + ASSERT_TRUE(args.has_value()); + EXPECT_EQ(expectedState, std::get<0>(args.value())); +} + +void EventThreadTest::expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset) { + auto args = mVSyncSetPhaseOffsetCallRecorder.waitForCall(); + ASSERT_TRUE(args.has_value()); + EXPECT_EQ(expectedPhaseOffset, std::get<0>(args.value())); +} + +VSyncSource::Callback* EventThreadTest::expectVSyncSetCallbackCallReceived() { + auto callbackSet = mVSyncSetCallbackCallRecorder.waitForCall(); + return callbackSet.has_value() ? std::get<0>(callbackSet.value()) : nullptr; +} + +void EventThreadTest::expectInterceptCallReceived(nsecs_t expectedTimestamp) { + auto args = mInterceptVSyncCallRecorder.waitForCall(); + ASSERT_TRUE(args.has_value()); + EXPECT_EQ(expectedTimestamp, std::get<0>(args.value())); +} + +void EventThreadTest::expectVsyncEventReceivedByConnection( + const char* name, ConnectionEventRecorder& connectionEventRecorder, + nsecs_t expectedTimestamp, unsigned expectedCount) { + auto args = connectionEventRecorder.waitForCall(); + ASSERT_TRUE(args.has_value()) << name << " did not receive an event for timestamp " + << expectedTimestamp; + const auto& event = std::get<0>(args.value()); + EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_VSYNC, event.header.type) + << name << " did not get the correct event for timestamp " << expectedTimestamp; + EXPECT_EQ(expectedTimestamp, event.header.timestamp) + << name << " did not get the expected timestamp for timestamp " << expectedTimestamp; + EXPECT_EQ(expectedCount, event.vsync.count) + << name << " did not get the expected count for timestamp " << expectedTimestamp; +} + +void EventThreadTest::expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, + unsigned expectedCount) { + expectVsyncEventReceivedByConnection("mConnectionEventCallRecorder", + mConnectionEventCallRecorder, expectedTimestamp, + expectedCount); +} + +void EventThreadTest::expectHotplugEventReceivedByConnection(int expectedDisplayType, + bool expectedConnected) { + auto args = mConnectionEventCallRecorder.waitForCall(); + ASSERT_TRUE(args.has_value()); + const auto& event = std::get<0>(args.value()); + EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, event.header.type); + EXPECT_EQ(static_cast(expectedDisplayType), event.header.id); + EXPECT_EQ(expectedConnected, event.hotplug.connected); +} + +namespace { + +/* ------------------------------------------------------------------------ + * Test cases + */ + +TEST_F(EventThreadTest, canCreateAndDestroyThreadWithNoEventsSent) { + EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value()); + EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value()); + EXPECT_FALSE(mVSyncSetPhaseOffsetCallRecorder.waitForCall(0us).has_value()); + EXPECT_FALSE(mResyncCallRecorder.waitForCall(0us).has_value()); + EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall(0us).has_value()); + EXPECT_FALSE(mConnectionEventCallRecorder.waitForCall(0us).has_value()); +} + +TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) { + // Signal that we want the next vsync event to be posted to the connection + mThread->requestNextVsync(mConnection); + + // EventThread should immediately request a resync. + EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value()); + + // EventThread should enable vsync callbacks, and set a callback interface + // pointer to use them with the VSync source. + expectVSyncSetEnabledCallReceived(true); + auto callback = expectVSyncSetCallbackCallReceived(); + ASSERT_TRUE(callback); + + // Use the received callback to signal a first vsync event. + // The interceptor should receive the event, as well as the connection. + callback->onVSyncEvent(123); + expectInterceptCallReceived(123); + expectVsyncEventReceivedByConnection(123, 1u); + + // Use the received callback to signal a second vsync event. + // The interceptor should receive the event, but the the connection should + // not as it was only interested in the first. + callback->onVSyncEvent(456); + expectInterceptCallReceived(456); + EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); + + // EventThread should also detect that at this point that it does not need + // any more vsync events, and should disable their generation. + expectVSyncSetEnabledCallReceived(false); +} + +TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) { + // Create a first connection, register it, and request a vsync rate of zero. + ConnectionEventRecorder firstConnectionEventRecorder{0}; + sp firstConnection = createConnection(firstConnectionEventRecorder); + mThread->setVsyncRate(0, firstConnection); + + // By itself, this should not enable vsync events + EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value()); + EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value()); + + // However if there is another connection which wants events at a nonzero rate..... + ConnectionEventRecorder secondConnectionEventRecorder{0}; + sp secondConnection = + createConnection(secondConnectionEventRecorder); + mThread->setVsyncRate(1, secondConnection); + + // EventThread should enable vsync callbacks, and set a callback interface + // pointer to use them with the VSync source. + expectVSyncSetEnabledCallReceived(true); + auto callback = expectVSyncSetCallbackCallReceived(); + ASSERT_TRUE(callback); + + // Send a vsync event. EventThread should then make a call to the + // interceptor, and the second connection. The first connection should not + // get the event. + callback->onVSyncEvent(123); + expectInterceptCallReceived(123); + EXPECT_FALSE(firstConnectionEventRecorder.waitForUnexpectedCall().has_value()); + expectVsyncEventReceivedByConnection("secondConnection", secondConnectionEventRecorder, 123, + 1u); +} + +TEST_F(EventThreadTest, setVsyncRateOnePostsAllEventsToThatConnection) { + mThread->setVsyncRate(1, mConnection); + + // EventThread should enable vsync callbacks, and set a callback interface + // pointer to use them with the VSync source. + expectVSyncSetEnabledCallReceived(true); + auto callback = expectVSyncSetCallbackCallReceived(); + ASSERT_TRUE(callback); + + // Send a vsync event. EventThread should then make a call to the + // interceptor, and the connection. + callback->onVSyncEvent(123); + expectInterceptCallReceived(123); + expectVsyncEventReceivedByConnection(123, 1u); + + // A second event should go to the same places. + callback->onVSyncEvent(456); + expectInterceptCallReceived(456); + expectVsyncEventReceivedByConnection(456, 2u); + + // A third event should go to the same places. + callback->onVSyncEvent(789); + expectInterceptCallReceived(789); + expectVsyncEventReceivedByConnection(789, 3u); +} + +TEST_F(EventThreadTest, setVsyncRateTwoPostsEveryOtherEventToThatConnection) { + mThread->setVsyncRate(2, mConnection); + + // EventThread should enable vsync callbacks, and set a callback interface + // pointer to use them with the VSync source. + expectVSyncSetEnabledCallReceived(true); + auto callback = expectVSyncSetCallbackCallReceived(); + ASSERT_TRUE(callback); + + // The first event will be seen by the interceptor, and not the connection. + callback->onVSyncEvent(123); + expectInterceptCallReceived(123); + EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); + + // The second event will be seen by the interceptor and the connection. + callback->onVSyncEvent(456); + expectInterceptCallReceived(456); + expectVsyncEventReceivedByConnection(456, 2u); + + // The third event will be seen by the interceptor, and not the connection. + callback->onVSyncEvent(789); + expectInterceptCallReceived(789); + EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); + + // The fourth event will be seen by the interceptor and the connection. + callback->onVSyncEvent(101112); + expectInterceptCallReceived(101112); + expectVsyncEventReceivedByConnection(101112, 4u); +} + +TEST_F(EventThreadTest, connectionsRemovedIfInstanceDestroyed) { + mThread->setVsyncRate(1, mConnection); + + // EventThread should enable vsync callbacks, and set a callback interface + // pointer to use them with the VSync source. + expectVSyncSetEnabledCallReceived(true); + auto callback = expectVSyncSetCallbackCallReceived(); + ASSERT_TRUE(callback); + + // Destroy the only (strong) reference to the connection. + mConnection = nullptr; + + // The first event will be seen by the interceptor, and not the connection. + callback->onVSyncEvent(123); + expectInterceptCallReceived(123); + EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); + + // EventThread should disable vsync callbacks + expectVSyncSetEnabledCallReceived(false); +} + +TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) { + ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY}; + sp errorConnection = createConnection(errorConnectionEventRecorder); + mThread->setVsyncRate(1, errorConnection); + + // EventThread should enable vsync callbacks, and set a callback interface + // pointer to use them with the VSync source. + expectVSyncSetEnabledCallReceived(true); + auto callback = expectVSyncSetCallbackCallReceived(); + ASSERT_TRUE(callback); + + // The first event will be seen by the interceptor, and by the connection, + // which then returns an error. + callback->onVSyncEvent(123); + expectInterceptCallReceived(123); + expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u); + + // A subsequent event will be seen by the interceptor and not by the + // connection. + callback->onVSyncEvent(456); + expectInterceptCallReceived(456); + EXPECT_FALSE(errorConnectionEventRecorder.waitForUnexpectedCall().has_value()); + + // EventThread should disable vsync callbacks with the second event + expectVSyncSetEnabledCallReceived(false); +} + +TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) { + ConnectionEventRecorder errorConnectionEventRecorder{WOULD_BLOCK}; + sp errorConnection = createConnection(errorConnectionEventRecorder); + mThread->setVsyncRate(1, errorConnection); + + // EventThread should enable vsync callbacks, and set a callback interface + // pointer to use them with the VSync source. + expectVSyncSetEnabledCallReceived(true); + auto callback = expectVSyncSetCallbackCallReceived(); + ASSERT_TRUE(callback); + + // The first event will be seen by the interceptor, and by the connection, + // which then returns an non-fatal error. + callback->onVSyncEvent(123); + expectInterceptCallReceived(123); + expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u); + + // A subsequent event will be seen by the interceptor, and by the connection, + // which still then returns an non-fatal error. + callback->onVSyncEvent(456); + expectInterceptCallReceived(456); + expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 456, 2u); + + // EventThread will not disable vsync callbacks as the errors are non-fatal. + EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value()); +} + +TEST_F(EventThreadTest, setPhaseOffsetForwardsToVSyncSource) { + mThread->setPhaseOffset(321); + expectVSyncSetPhaseOffsetCallReceived(321); +} + +TEST_F(EventThreadTest, postHotplugPrimaryDisconnect) { + mThread->onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, false); + expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_PRIMARY, false); +} + +TEST_F(EventThreadTest, postHotplugPrimaryConnect) { + mThread->onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, true); + expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_PRIMARY, true); +} + +TEST_F(EventThreadTest, postHotplugExternalDisconnect) { + mThread->onHotplugReceived(DisplayDevice::DISPLAY_EXTERNAL, false); + expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_EXTERNAL, false); +} + +TEST_F(EventThreadTest, postHotplugExternalConnect) { + mThread->onHotplugReceived(DisplayDevice::DISPLAY_EXTERNAL, true); + expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_EXTERNAL, true); +} + +TEST_F(EventThreadTest, postHotplugVirtualDisconnectIsFilteredOut) { + mThread->onHotplugReceived(DisplayDevice::DISPLAY_VIRTUAL, false); + EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); +} + +} // namespace +} // namespace android -- cgit v1.2.3-59-g8ed1b From 243b378f47552ab6916fc9b92557c0df0557fd98 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Tue, 15 May 2018 17:40:04 -0700 Subject: SF: Fix IGBP list leak This change fixed the IGBP list leak. Bug: b/77602128 Test: open and close an app repeatedly and check the GraphicBufferProducers size in dumpsys SurfaceFlinger Change-Id: I2dbf4ee2c20c4404bfb15bbc2ab89df5783d90a4 --- services/surfaceflinger/SurfaceFlinger.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 588d24c45f..d69f996516 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -316,8 +316,7 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { mLayerTripleBufferingDisabled = atoi(value); ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering"); - // TODO (b/74616334): Reduce the default value once we isolate the leak - const size_t defaultListSize = 4 * MAX_LAYERS; + const size_t defaultListSize = MAX_LAYERS; auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize)); mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize; @@ -3150,12 +3149,14 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, parent->addChild(lbc); } - mGraphicBufferProducerList.insert(IInterface::asBinder(gbc).get()); - // TODO (b/74616334): Change this back to a fatal assert once the leak is fixed - ALOGE_IF(mGraphicBufferProducerList.size() > mMaxGraphicBufferProducerListSize, - "Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers", - mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize, - mNumLayers); + if (gbc != nullptr) { + mGraphicBufferProducerList.insert(IInterface::asBinder(gbc).get()); + LOG_ALWAYS_FATAL_IF(mGraphicBufferProducerList.size() > + mMaxGraphicBufferProducerListSize, + "Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers", + mGraphicBufferProducerList.size(), + mMaxGraphicBufferProducerListSize, mNumLayers); + } mLayersAdded = true; mNumLayers++; } -- cgit v1.2.3-59-g8ed1b From 36574d99f78bb533db4eaeb35998bb96f2e69193 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 16 May 2018 10:54:36 -0700 Subject: surfaceflinger: fix screenshot dataspace under WCG Commit a252d8958 (Use GraphicBuffer instead of GBP for screenshots) removed the ability to query the dataspace of the screenshots. WM assumes they are sRGB anyway. Let's force screenshots to be in sRGB. Bug: 79547689 Test: no color shift during Photos rotation Change-Id: If57cba1b5a50c4e1f9b305af39d9588b3dd1775d --- services/surfaceflinger/DisplayDevice.h | 7 ------- services/surfaceflinger/RenderArea.h | 3 --- services/surfaceflinger/SurfaceFlinger.cpp | 15 +++------------ 3 files changed, 3 insertions(+), 22 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index d051e33579..b4100ce976 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -336,13 +336,6 @@ public: bool isSecure() const override { return mDevice->isSecure(); } bool needsFiltering() const override { return mDevice->needsFiltering(); } Rect getSourceCrop() const override { return mSourceCrop; } - bool getWideColorSupport() const override { return mDevice->hasWideColorGamut(); } - ui::Dataspace getDataSpace() const override { - return mDevice->getCompositionDataSpace(); - } - float getDisplayMaxLuminance() const override { - return mDevice->getHdrCapabilities().getDesiredMaxLuminance(); - } private: const sp mDevice; diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 4694403c2d..938c3ce0dd 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -30,9 +30,6 @@ public: virtual bool isSecure() const = 0; virtual bool needsFiltering() const = 0; virtual Rect getSourceCrop() const = 0; - virtual bool getWideColorSupport() const = 0; - virtual ui::Dataspace getDataSpace() const = 0; - virtual float getDisplayMaxLuminance() const = 0; virtual void render(std::function drawLayers) { drawLayers(); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c687e9db93..8148bd7db8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4810,12 +4810,6 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, return mCrop; } } - bool getWideColorSupport() const override { return false; } - Dataspace getDataSpace() const override { return Dataspace::UNKNOWN; } - float getDisplayMaxLuminance() const override { - return DisplayDevice::sDefaultMaxLumiance; - } - class ReparentForDrawing { public: const sp& oldParent; @@ -5013,12 +5007,9 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight); } - Dataspace outputDataspace = Dataspace::UNKNOWN; - if (renderArea.getWideColorSupport()) { - outputDataspace = renderArea.getDataSpace(); - } - engine.setOutputDataSpace(outputDataspace); - engine.setDisplayMaxLuminance(renderArea.getDisplayMaxLuminance()); + // assume ColorMode::SRGB / RenderIntent::COLORIMETRIC + engine.setOutputDataSpace(Dataspace::SRGB); + engine.setDisplayMaxLuminance(DisplayDevice::sDefaultMaxLumiance); // make sure to clear all GL error flags engine.checkErrors(); -- cgit v1.2.3-59-g8ed1b From e1043320e8634fb100b5bc2cca4c5ac1f3e9f483 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 17 May 2018 13:24:48 -0700 Subject: surfaceflinger: use layer drawing dataspace Layer::getDataSpace returns the current (as opposed to drawing) dataspace, which we almost never want and is racy. Remove the helper and access the dataspace directly. Bug: 79210409 Test: boots, Photos Change-Id: Ifec7055cf0a1f2d84da7ad58e27be2c01082e6e9 --- services/surfaceflinger/Layer.cpp | 8 ++------ services/surfaceflinger/Layer.h | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 10 +++++----- 3 files changed, 7 insertions(+), 12 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9043234132..2077598371 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1337,10 +1337,6 @@ bool Layer::setDataSpace(ui::Dataspace dataSpace) { return true; } -ui::Dataspace Layer::getDataSpace() const { - return mCurrentState.dataSpace; -} - uint32_t Layer::getLayerStack() const { auto p = mDrawingParent.promote(); if (p == nullptr) { @@ -1433,7 +1429,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); - info.mDataSpace = static_cast(getDataSpace()); + info.mDataSpace = static_cast(ds.dataSpace); info.mMatrix[0][0] = ds.active.transform[0][0]; info.mMatrix[0][1] = ds.active.transform[0][1]; info.mMatrix[1][0] = ds.active.transform[1][0]; @@ -1960,7 +1956,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_is_opaque(isOpaque(state)); layerInfo->set_invalidate(contentDirty); - layerInfo->set_dataspace(dataspaceDetails(static_cast(getDataSpace()))); + layerInfo->set_dataspace(dataspaceDetails(static_cast(state.dataSpace))); layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat())); LayerProtoHelper::writeToProto(getColor(), layerInfo->mutable_color()); LayerProtoHelper::writeToProto(state.color, layerInfo->mutable_requested_color()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 632efbe23e..91eb15ae4a 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -288,7 +288,6 @@ public: bool setFlags(uint8_t flags, uint8_t mask); bool setLayerStack(uint32_t layerStack); bool setDataSpace(ui::Dataspace dataSpace); - ui::Dataspace getDataSpace() const; uint32_t getLayerStack() const; void deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber); void deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 84893a7c2e..c5d311bb89 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1870,7 +1870,7 @@ Dataspace SurfaceFlinger::getBestDataspace( *outHdrDataSpace = Dataspace::UNKNOWN; for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - switch (layer->getDataSpace()) { + switch (layer->getDrawingState().dataSpace) { case Dataspace::V0_SCRGB: case Dataspace::V0_SCRGB_LINEAR: bestDataSpace = Dataspace::V0_SCRGB_LINEAR; @@ -2089,13 +2089,13 @@ void SurfaceFlinger::setUpHWComposer() { "display %zd: %d", displayId, result); } for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - if ((layer->getDataSpace() == Dataspace::BT2020_PQ || - layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && + if ((layer->getDrawingState().dataSpace == Dataspace::BT2020_PQ || + layer->getDrawingState().dataSpace == Dataspace::BT2020_ITU_PQ) && !displayDevice->hasHDR10Support()) { layer->forceClientComposition(hwcId); } - if ((layer->getDataSpace() == Dataspace::BT2020_HLG || - layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && + if ((layer->getDrawingState().dataSpace == Dataspace::BT2020_HLG || + layer->getDrawingState().dataSpace == Dataspace::BT2020_ITU_HLG) && !displayDevice->hasHLGSupport()) { layer->forceClientComposition(hwcId); } -- cgit v1.2.3-59-g8ed1b From 3c085a07a84bc03aefb2c0caf24a1ae1a9f5f90c Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 9 May 2018 19:38:32 -0700 Subject: SF: Initialize DisplayDevice with the active config index This is a port of aosp/580542, with added unit test changes now that the correct config is being set in the DisplayDevice. Bug: 69807179 Test: atest libsurfaceflinger_unittest Change-Id: I51c13678bc28c715fa116ad127478d4afa3d0349 --- services/surfaceflinger/DisplayHardware/HWC2.cpp | 28 +++++++++++++++++++++- services/surfaceflinger/DisplayHardware/HWC2.h | 6 ++--- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 22 +++++++++++++++++ .../surfaceflinger/DisplayHardware/HWComposer.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 3 +++ .../tests/unittests/DisplayTransactionTest.cpp | 20 ++++++---------- 6 files changed, 62 insertions(+), 18 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 3947318262..61758b63f1 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -30,8 +30,9 @@ #include -#include #include +#include +#include #include using android::Fence; @@ -338,6 +339,31 @@ Error Display::getActiveConfig( return Error::None; } +Error Display::getActiveConfigIndex(int* outIndex) const { + ALOGV("[%" PRIu64 "] getActiveConfigIndex", mId); + hwc2_config_t configId = 0; + auto intError = mComposer.getActiveConfig(mId, &configId); + auto error = static_cast(intError); + + if (error != Error::None) { + ALOGE("Unable to get active config for mId:[%" PRIu64 "]", mId); + *outIndex = -1; + return error; + } + + auto pos = mConfigs.find(configId); + if (pos != mConfigs.end()) { + *outIndex = std::distance(mConfigs.begin(), pos); + } else { + ALOGE("[%" PRIu64 "] getActiveConfig returned unknown config %u", mId, configId); + // Return no error, but the caller needs to check for a negative index + // to detect this case + *outIndex = -1; + } + + return Error::None; +} + Error Display::getChangedCompositionTypes( std::unordered_map* outTypes) { diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 3ac06ec192..29d7a47ad8 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -36,7 +36,6 @@ #include #include #include -#include namespace android { class Fence; @@ -207,6 +206,7 @@ public: [[clang::warn_unused_result]] Error destroyLayer(Layer* layer); [[clang::warn_unused_result]] Error getActiveConfig( std::shared_ptr* outConfig) const; + [[clang::warn_unused_result]] Error getActiveConfigIndex(int* outIndex) const; [[clang::warn_unused_result]] Error getChangedCompositionTypes( std::unordered_map* outTypes); [[clang::warn_unused_result]] Error getColorModes( @@ -288,9 +288,7 @@ private: bool mIsConnected; DisplayType mType; std::unordered_map> mLayers; - // The ordering in this map matters, for getConfigs(), when it is - // converted to a vector - std::map> mConfigs; + std::unordered_map> mConfigs; }; // Convenience C++ class to access hwc2_device_t Layer functions directly. diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 96d691ce9c..f5f7a821f0 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -318,6 +318,28 @@ std::shared_ptr return config; } +int HWComposer::getActiveConfigIndex(int32_t displayId) const { + if (!isValidDisplay(displayId)) { + ALOGV("getActiveConfigIndex: Attempted to access invalid display %d", displayId); + return -1; + } + int index; + auto error = mDisplayData[displayId].hwcDisplay->getActiveConfigIndex(&index); + if (error == HWC2::Error::BadConfig) { + ALOGE("getActiveConfigIndex: No config active, returning -1"); + return -1; + } else if (error != HWC2::Error::None) { + ALOGE("getActiveConfigIndex failed for display %d: %s (%d)", displayId, + to_string(error).c_str(), static_cast(error)); + return -1; + } else if (index < 0) { + ALOGE("getActiveConfigIndex returned an unknown config for display %d", displayId); + return -1; + } + + return index; +} + std::vector HWComposer::getColorModes(int32_t displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index d7f3b08d48..f9689482cc 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -164,6 +164,7 @@ public: std::shared_ptr getActiveConfig(int32_t displayId) const; + int getActiveConfigIndex(int32_t displayId) const; std::vector getColorModes(int32_t displayId) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b35b58c6a8..9117207544 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2414,6 +2414,9 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( } setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace, RenderIntent::COLORIMETRIC); + if (state.type < DisplayDevice::DISPLAY_VIRTUAL) { + hw->setActiveConfig(getHwComposer().getActiveConfigIndex(state.type)); + } hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); hw->setDisplayName(state.displayName); diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index d1bbb5bd6e..cd691282d0 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -306,11 +306,7 @@ struct HwcDisplayVariant { static constexpr HWC2::DisplayType HWC_DISPLAY_TYPE = hwcDisplayType; // The HWC active configuration id - // TODO(b/69807179): SurfaceFlinger does not correctly get the active - // config. Once it does, change this to non-zero so that it is properly - // covered. - // static constexpr int HWC_ACTIVE_CONFIG_ID = 2001; - static constexpr int HWC_ACTIVE_CONFIG_ID = 0; + static constexpr int HWC_ACTIVE_CONFIG_ID = 2001; static void injectPendingHotplugEvent(DisplayTransactionTest* test, HWC2::Connection connection) { @@ -362,13 +358,11 @@ struct HwcDisplayVariant { // Called by tests to set up HWC call expectations static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY_ID, _)) - .WillOnce(DoAll(SetArgPointee<1>(HWC_ACTIVE_CONFIG_ID), Return(Error::NONE))); + .WillRepeatedly(DoAll(SetArgPointee<1>(HWC_ACTIVE_CONFIG_ID), Return(Error::NONE))); } }; struct NonHwcDisplayVariant { - static constexpr int HWC_ACTIVE_CONFIG_ID = 0; - static void injectHwcDisplay(DisplayTransactionTest*) {} static void setupHwcGetActiveConfigCallExpectations(DisplayTransactionTest* test) { @@ -1033,10 +1027,7 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { // Various native window calls will be made. Case::Display::setupNativeWindowSurfaceCreationCallExpectations(this); - - // TODO(b/69807179): SurfaceFlinger does not correctly get the active config. - // Case::Display::setupHwcGetActiveConfigCallExpectations(this) - + Case::Display::setupHwcGetActiveConfigCallExpectations(this); Case::WideColorSupport::setupComposerCallExpectations(this); Case::HdrSupport::setupComposerCallExpectations(this); Case::PerFrameMetadataSupport::setupComposerCallExpectations(this); @@ -1060,7 +1051,10 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { EXPECT_EQ(Case::HdrSupport::HDR10_SUPPORTED, device->hasHDR10Support()); EXPECT_EQ(Case::HdrSupport::HDR_HLG_SUPPORTED, device->hasHLGSupport()); EXPECT_EQ(Case::HdrSupport::HDR_DOLBY_VISION_SUPPORTED, device->hasDolbyVisionSupport()); - EXPECT_EQ(Case::Display::HWC_ACTIVE_CONFIG_ID, device->getActiveConfig()); + // Note: This is not Case::Display::HWC_ACTIVE_CONFIG_ID as the ids are + // remapped, and the test only ever sets up one config. If there were an error + // looking up the remapped index, device->getActiveConfig() would be -1 instead. + EXPECT_EQ(0, device->getActiveConfig()); EXPECT_EQ(Case::PerFrameMetadataSupport::PER_FRAME_METADATA_KEYS, device->getSupportedPerFrameMetadata()); } -- cgit v1.2.3-59-g8ed1b From 1b6bafca6e5c4a71bc97f14be30e64541633bda7 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 22 May 2018 12:03:00 -0700 Subject: surfaceflinger: layer dataspace is not a state Like current crop or transform, layer dataspace is latched with the buffer. It is not a layer state, and should take effect immediately. Bug: 80139629 Test: manual Change-Id: I52342ca345f174e647550b45defa977484db95a1 Merged-In: I52342ca345f174e647550b45defa977484db95a1 --- services/surfaceflinger/BufferLayer.cpp | 12 ++++++------ services/surfaceflinger/ColorLayer.cpp | 4 ++-- services/surfaceflinger/Layer.cpp | 20 +++++++------------- services/surfaceflinger/Layer.h | 5 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 10 +++++----- 5 files changed, 23 insertions(+), 28 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 6feec53257..17ed9aa00c 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -553,7 +553,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime default: break; } - setDataSpace(dataSpace); + mCurrentDataSpace = dataSpace; Rect crop(mConsumer->getCurrentCrop()); const uint32_t transform(mConsumer->getCurrentTransform()); @@ -660,10 +660,10 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) setCompositionType(hwcId, HWC2::Composition::Device); } - ALOGV("setPerFrameData: dataspace = %d", mDrawingState.dataSpace); - error = hwcLayer->setDataspace(mDrawingState.dataSpace); + ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace); + error = hwcLayer->setDataspace(mCurrentDataSpace); if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mDrawingState.dataSpace, + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, to_string(error).c_str(), static_cast(error)); } @@ -866,9 +866,9 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT auto& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */, getColor()); - engine.setSourceDataSpace(mCurrentState.dataSpace); + engine.setSourceDataSpace(mCurrentDataSpace); - if (mCurrentState.dataSpace == ui::Dataspace::BT2020_ITU_PQ && + if (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA && getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) { engine.setSourceY410BT2020(true); diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index c87b66981d..512564c2db 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -77,9 +77,9 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { setCompositionType(hwcId, HWC2::Composition::SolidColor); - error = hwcLayer->setDataspace(mDrawingState.dataSpace); + error = hwcLayer->setDataspace(mCurrentDataSpace); if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mDrawingState.dataSpace, + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace, to_string(error).c_str(), static_cast(error)); } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2077598371..b94af77967 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -123,7 +123,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mCurrentState.layerStack = 0; mCurrentState.sequence = 0; mCurrentState.requested = mCurrentState.active; - mCurrentState.dataSpace = ui::Dataspace::UNKNOWN; mCurrentState.appId = 0; mCurrentState.type = 0; @@ -1328,15 +1327,6 @@ bool Layer::setLayerStack(uint32_t layerStack) { return true; } -bool Layer::setDataSpace(ui::Dataspace dataSpace) { - if (mCurrentState.dataSpace == dataSpace) return false; - mCurrentState.sequence++; - mCurrentState.dataSpace = dataSpace; - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; -} - uint32_t Layer::getLayerStack() const { auto p = mDrawingParent.promote(); if (p == nullptr) { @@ -1429,7 +1419,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); - info.mDataSpace = static_cast(ds.dataSpace); + info.mDataSpace = static_cast(mCurrentDataSpace); info.mMatrix[0][0] = ds.active.transform[0][0]; info.mMatrix[0][1] = ds.active.transform[0][1]; info.mMatrix[1][0] = ds.active.transform[1][0]; @@ -1648,7 +1638,7 @@ bool Layer::detachChildren() { bool Layer::isLegacyDataSpace() const { // return true when no higher bits are set - return !(mDrawingState.dataSpace & (ui::Dataspace::STANDARD_MASK | + return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK | ui::Dataspace::TRANSFER_MASK | ui::Dataspace::RANGE_MASK)); } @@ -1956,7 +1946,10 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_is_opaque(isOpaque(state)); layerInfo->set_invalidate(contentDirty); - layerInfo->set_dataspace(dataspaceDetails(static_cast(state.dataSpace))); + + // XXX (b/79210409) mCurrentDataSpace is not protected + layerInfo->set_dataspace(dataspaceDetails(static_cast(mCurrentDataSpace))); + layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat())); LayerProtoHelper::writeToProto(getColor(), layerInfo->mutable_color()); LayerProtoHelper::writeToProto(state.color, layerInfo->mutable_requested_color()); @@ -1975,6 +1968,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence); } + // XXX getBE().compositionInfo.mBuffer is not protected auto buffer = getBE().compositionInfo.mBuffer; if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, layerInfo->mutable_active_buffer()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 91eb15ae4a..7342c8b987 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -209,7 +209,6 @@ public: // dependent. Region activeTransparentRegion; Region requestedTransparentRegion; - ui::Dataspace dataSpace; int32_t appId; int32_t type; @@ -287,7 +286,6 @@ public: bool setTransparentRegionHint(const Region& transparent); bool setFlags(uint8_t flags, uint8_t mask); bool setLayerStack(uint32_t layerStack); - bool setDataSpace(ui::Dataspace dataSpace); uint32_t getLayerStack() const; void deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber); void deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber); @@ -298,6 +296,8 @@ public: bool reparent(const sp& newParentHandle); bool detachChildren(); + ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } + // Before color management is introduced, contents on Android have to be // desaturated in order to match what they appears like visually. // With color management, these contents will appear desaturated, thus @@ -743,6 +743,7 @@ protected: int mActiveBufferSlot; sp mActiveBuffer; sp mSidebandStream; + ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN; Rect mCurrentCrop; uint32_t mCurrentTransform; // We encode unset as -1. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9117207544..e7892ef109 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1879,7 +1879,7 @@ Dataspace SurfaceFlinger::getBestDataspace( *outHdrDataSpace = Dataspace::UNKNOWN; for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - switch (layer->getDrawingState().dataSpace) { + switch (layer->getDataSpace()) { case Dataspace::V0_SCRGB: case Dataspace::V0_SCRGB_LINEAR: bestDataSpace = Dataspace::V0_SCRGB_LINEAR; @@ -2098,13 +2098,13 @@ void SurfaceFlinger::setUpHWComposer() { "display %zd: %d", displayId, result); } for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - if ((layer->getDrawingState().dataSpace == Dataspace::BT2020_PQ || - layer->getDrawingState().dataSpace == Dataspace::BT2020_ITU_PQ) && + if ((layer->getDataSpace() == Dataspace::BT2020_PQ || + layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && !displayDevice->hasHDR10Support()) { layer->forceClientComposition(hwcId); } - if ((layer->getDrawingState().dataSpace == Dataspace::BT2020_HLG || - layer->getDrawingState().dataSpace == Dataspace::BT2020_ITU_HLG) && + if ((layer->getDataSpace() == Dataspace::BT2020_HLG || + layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && !displayDevice->hasHLGSupport()) { layer->forceClientComposition(hwcId); } -- cgit v1.2.3-59-g8ed1b From 0607fbe8956a64151b165ac88ef9f3cf9b4ece5d Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 18 May 2018 10:59:36 -0700 Subject: surfaceflinger: compute color mode mappings on hotplug Populuate DisplayDevice::mColorModes when a DisplayDevice is created. DisplayDevice::mColorModes is a map from any possible Dataspace/RenderIntent to supported Dataspace/ColorMode/RenderIntent. This makes sure we never ask the composer to use an unsupported Dataspace/ColorMode/RenderIntent combination. The map is populated on hotplug because we don't want to compute the mapping on the fly at each frame. Bug: 79843697 Bug: 75981986 Test: manual under sRGB, P3, HDR Change-Id: I967d09b1e8d31ea631b202db1799a7a2a0c5ee3f Merged-In: I967d09b1e8d31ea631b202db1799a7a2a0c5ee3f --- services/surfaceflinger/DisplayDevice.cpp | 259 +++++++++++++++++++++++++---- services/surfaceflinger/DisplayDevice.h | 48 ++++-- services/surfaceflinger/SurfaceFlinger.cpp | 133 ++------------- services/surfaceflinger/SurfaceFlinger.h | 2 - 4 files changed, 278 insertions(+), 164 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index f6eac8b08a..ccd2aba728 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -18,6 +18,9 @@ #undef LOG_TAG #define LOG_TAG "DisplayDevice" +#include +#include + #include #include #include @@ -55,6 +58,7 @@ namespace android { using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; using android::ui::ColorMode; +using android::ui::Dataspace; using android::ui::Hdr; using android::ui::RenderIntent; @@ -65,6 +69,147 @@ using android::ui::RenderIntent; uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0; +namespace { + +// ordered list of known SDR color modes +const std::array sSdrColorModes = { + ColorMode::DISPLAY_P3, + ColorMode::SRGB, +}; + +// ordered list of known HDR color modes +const std::array sHdrColorModes = { + ColorMode::BT2100_PQ, + ColorMode::BT2100_HLG, +}; + +// ordered list of known SDR render intents +const std::array sSdrRenderIntents = { + RenderIntent::ENHANCE, + RenderIntent::COLORIMETRIC, +}; + +// ordered list of known HDR render intents +const std::array sHdrRenderIntents = { + RenderIntent::TONE_MAP_ENHANCE, + RenderIntent::TONE_MAP_COLORIMETRIC, +}; + +// map known color mode to dataspace +Dataspace colorModeToDataspace(ColorMode mode) { + switch (mode) { + case ColorMode::SRGB: + return Dataspace::SRGB; + case ColorMode::DISPLAY_P3: + return Dataspace::DISPLAY_P3; + case ColorMode::BT2100_HLG: + return Dataspace::BT2020_HLG; + case ColorMode::BT2100_PQ: + return Dataspace::BT2020_PQ; + default: + return Dataspace::UNKNOWN; + } +} + +// Return a list of candidate color modes. +std::vector getColorModeCandidates(ColorMode mode) { + std::vector candidates; + + // add mode itself + candidates.push_back(mode); + + // check if mode is HDR + bool isHdr = false; + for (auto hdrMode : sHdrColorModes) { + if (hdrMode == mode) { + isHdr = true; + break; + } + } + + // add other HDR candidates when mode is HDR + if (isHdr) { + for (auto hdrMode : sHdrColorModes) { + if (hdrMode != mode) { + candidates.push_back(hdrMode); + } + } + } + + // add other SDR candidates + for (auto sdrMode : sSdrColorModes) { + if (sdrMode != mode) { + candidates.push_back(sdrMode); + } + } + + return candidates; +} + +// Return a list of candidate render intents. +std::vector getRenderIntentCandidates(RenderIntent intent) { + std::vector candidates; + + // add intent itself + candidates.push_back(intent); + + // check if intent is HDR + bool isHdr = false; + for (auto hdrIntent : sHdrRenderIntents) { + if (hdrIntent == intent) { + isHdr = true; + break; + } + } + + // add other HDR candidates when intent is HDR + if (isHdr) { + for (auto hdrIntent : sHdrRenderIntents) { + if (hdrIntent != intent) { + candidates.push_back(hdrIntent); + } + } + } + + // add COLORIMETRIC + if (intent != RenderIntent::COLORIMETRIC) { + candidates.push_back(RenderIntent::COLORIMETRIC); + } + + return candidates; +} + +// Return the best color mode supported by HWC. +ColorMode getHwcColorMode( + const std::unordered_map>& hwcColorModes, + ColorMode mode) { + std::vector candidates = getColorModeCandidates(mode); + for (auto candidate : candidates) { + auto iter = hwcColorModes.find(candidate); + if (iter != hwcColorModes.end()) { + return candidate; + } + } + + return ColorMode::NATIVE; +} + +// Return the best render intent supported by HWC. +RenderIntent getHwcRenderIntent(const std::vector& hwcIntents, RenderIntent intent) { + std::vector candidates = getRenderIntentCandidates(intent); + for (auto candidate : candidates) { + for (auto hwcIntent : hwcIntents) { + if (candidate == hwcIntent) { + return candidate; + } + } + } + + return RenderIntent::COLORIMETRIC; +} + +} // anonymous namespace + // clang-format off DisplayDevice::DisplayDevice( const sp& flinger, @@ -80,7 +225,7 @@ DisplayDevice::DisplayDevice( bool hasWideColorGamut, const HdrCapabilities& hdrCapabilities, const int32_t supportedPerFrameMetadata, - const std::unordered_map>& hdrAndRenderIntents, + const std::unordered_map>& hwcColorModes, int initialPowerMode) : lastCompositionHadVisibleLayers(false), mFlinger(flinger), @@ -105,13 +250,11 @@ DisplayDevice::DisplayDevice( mHasHdr10(false), mHasHLG(false), mHasDolbyVision(false), - mSupportedPerFrameMetadata(supportedPerFrameMetadata), - mHasBT2100PQColorimetric(false), - mHasBT2100PQEnhance(false), - mHasBT2100HLGColorimetric(false), - mHasBT2100HLGEnhance(false) + mSupportedPerFrameMetadata(supportedPerFrameMetadata) { // clang-format on + populateColorModes(hwcColorModes); + std::vector types = hdrCapabilities.getSupportedHdrTypes(); for (Hdr hdrType : types) { switch (hdrType) { @@ -149,18 +292,6 @@ DisplayDevice::DisplayDevice( } mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance); - auto iter = hdrAndRenderIntents.find(ColorMode::BT2100_PQ); - if (iter != hdrAndRenderIntents.end()) { - hasToneMapping(iter->second, - &mHasBT2100PQColorimetric, &mHasBT2100PQEnhance); - } - - iter = hdrAndRenderIntents.find(ColorMode::BT2100_HLG); - if (iter != hdrAndRenderIntents.end()) { - hasToneMapping(iter->second, - &mHasBT2100HLGColorimetric, &mHasBT2100HLGEnhance); - } - // initialize the display orientation transform. setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); } @@ -545,20 +676,88 @@ void DisplayDevice::dump(String8& result) const { result.append(surfaceDump); } -void DisplayDevice::hasToneMapping(const std::vector& renderIntents, - bool* outColorimetric, bool *outEnhance) { - for (auto intent : renderIntents) { - switch (intent) { - case RenderIntent::TONE_MAP_COLORIMETRIC: - *outColorimetric = true; - break; - case RenderIntent::TONE_MAP_ENHANCE: - *outEnhance = true; - break; - default: - break; +// Map dataspace/intent to the best matched dataspace/colorMode/renderIntent +// supported by HWC. +void DisplayDevice::addColorMode( + const std::unordered_map>& hwcColorModes, + const ColorMode mode, const RenderIntent intent) { + // find the best color mode + const ColorMode hwcColorMode = getHwcColorMode(hwcColorModes, mode); + + // find the best render intent + auto iter = hwcColorModes.find(hwcColorMode); + const auto& hwcIntents = + iter != hwcColorModes.end() ? iter->second : std::vector(); + const RenderIntent hwcIntent = getHwcRenderIntent(hwcIntents, intent); + + const Dataspace dataspace = colorModeToDataspace(mode); + const Dataspace hwcDataspace = colorModeToDataspace(hwcColorMode); + + ALOGV("DisplayDevice %d/%d: map (%s, %s) to (%s, %s, %s)", mType, mHwcDisplayId, + dataspaceDetails(static_cast(dataspace)).c_str(), + decodeRenderIntent(intent).c_str(), + dataspaceDetails(static_cast(hwcDataspace)).c_str(), + decodeColorMode(hwcColorMode).c_str(), decodeRenderIntent(hwcIntent).c_str()); + + mColorModes[getColorModeKey(dataspace, intent)] = {hwcDataspace, hwcColorMode, hwcIntent}; +} + +void DisplayDevice::populateColorModes( + const std::unordered_map>& hwcColorModes) { + if (!hasWideColorGamut()) { + return; + } + + // add known SDR combinations + for (auto intent : sSdrRenderIntents) { + for (auto mode : sSdrColorModes) { + addColorMode(hwcColorModes, mode, intent); } } + + // add known HDR combinations + for (auto intent : sHdrRenderIntents) { + for (auto mode : sHdrColorModes) { + addColorMode(hwcColorModes, mode, intent); + } + } +} + +bool DisplayDevice::hasRenderIntent(RenderIntent intent) const { + // assume a render intent is supported when SRGB supports it; we should + // get rid of that assumption. + auto iter = mColorModes.find(getColorModeKey(Dataspace::SRGB, intent)); + return iter != mColorModes.end() && iter->second.renderIntent == intent; +} + +bool DisplayDevice::hasModernHdrSupport(Dataspace dataspace) const { + if ((dataspace == Dataspace::BT2020_PQ && hasHDR10Support()) || + (dataspace == Dataspace::BT2020_HLG && hasHLGSupport())) { + auto iter = + mColorModes.find(getColorModeKey(dataspace, RenderIntent::TONE_MAP_COLORIMETRIC)); + return iter != mColorModes.end() && iter->second.dataspace == dataspace; + } + + return false; +} + +void DisplayDevice::getBestColorMode(Dataspace dataspace, RenderIntent intent, + Dataspace* outDataspace, ColorMode* outMode, + RenderIntent* outIntent) const { + auto iter = mColorModes.find(getColorModeKey(dataspace, intent)); + if (iter != mColorModes.end()) { + *outDataspace = iter->second.dataspace; + *outMode = iter->second.colorMode; + *outIntent = iter->second.renderIntent; + } else { + ALOGE("map unknown (%s)/(%s) to default color mode", + dataspaceDetails(static_cast(dataspace)).c_str(), + decodeRenderIntent(intent).c_str()); + + *outDataspace = Dataspace::UNKNOWN; + *outMode = ColorMode::NATIVE; + *outIntent = RenderIntent::COLORIMETRIC; + } } std::atomic DisplayDeviceState::nextDisplayId(1); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 883f53313a..b3859b6793 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -91,7 +91,7 @@ public: bool hasWideColorGamut, const HdrCapabilities& hdrCapabilities, const int32_t supportedPerFrameMetadata, - const std::unordered_map>& hdrAndRenderIntents, + const std::unordered_map>& hwcColorModes, int initialPowerMode); // clang-format on @@ -143,11 +143,17 @@ public: // machine happy without actually queueing a buffer if nothing has changed status_t beginFrame(bool mustRecompose) const; status_t prepareFrame(HWComposer& hwc); + bool hasWideColorGamut() const { return mHasWideColorGamut; } // Whether h/w composer has native support for specific HDR type. bool hasHDR10Support() const { return mHasHdr10; } bool hasHLGSupport() const { return mHasHLG; } bool hasDolbyVisionSupport() const { return mHasDolbyVision; } + + // Return true if the corresponding color mode for the HDR dataspace is + // supported. + bool hasModernHdrSupport(ui::Dataspace dataspace) const; + // The returned HdrCapabilities is the combination of HDR capabilities from // hardware composer and RenderEngine. When the DisplayDevice supports wide // color gamut, RenderEngine is able to simulate HDR support in Display P3 @@ -156,13 +162,12 @@ public: // respectively if hardware composer doesn't return meaningful values. const HdrCapabilities& getHdrCapabilities() const { return mHdrCapabilities; } - // Whether h/w composer has BT2100_PQ color mode. - bool hasBT2100PQColorimetricSupport() const { return mHasBT2100PQColorimetric; } - bool hasBT2100PQEnhanceSupport() const { return mHasBT2100PQEnhance; } + // Return true if intent is supported by the display. + bool hasRenderIntent(ui::RenderIntent intent) const; - // Whether h/w composer has BT2100_HLG color mode. - bool hasBT2100HLGColorimetricSupport() const { return mHasBT2100HLGColorimetric; } - bool hasBT2100HLGEnhanceSupport() const { return mHasBT2100HLGEnhance; } + void getBestColorMode(ui::Dataspace dataspace, ui::RenderIntent intent, + ui::Dataspace* outDataspace, ui::ColorMode* outMode, + ui::RenderIntent* outIntent) const; void swapBuffers(HWComposer& hwc) const; @@ -214,9 +219,6 @@ public: void dump(String8& result) const; private: - void hasToneMapping(const std::vector& renderIntents, - bool* outColorimetric, bool *outEnhance); - /* * Constants, set during initialization */ @@ -288,12 +290,26 @@ private: bool mHasDolbyVision; HdrCapabilities mHdrCapabilities; const int32_t mSupportedPerFrameMetadata; - // Whether h/w composer has BT2100_PQ and BT2100_HLG color mode with - // colorimetrical tone mapping or enhanced tone mapping. - bool mHasBT2100PQColorimetric; - bool mHasBT2100PQEnhance; - bool mHasBT2100HLGColorimetric; - bool mHasBT2100HLGEnhance; + + // Mappings from desired Dataspace/RenderIntent to the supported + // Dataspace/ColorMode/RenderIntent. + using ColorModeKey = uint64_t; + struct ColorModeValue { + ui::Dataspace dataspace; + ui::ColorMode colorMode; + ui::RenderIntent renderIntent; + }; + + static ColorModeKey getColorModeKey(ui::Dataspace dataspace, ui::RenderIntent intent) { + return (static_cast(dataspace) << 32) | static_cast(intent); + } + void populateColorModes( + const std::unordered_map>& hwcColorModes); + void addColorMode( + const std::unordered_map>& hwcColorModes, + const ui::ColorMode mode, const ui::RenderIntent intent); + + std::unordered_map mColorModes; }; struct DisplayDeviceState { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e7892ef109..e7e3eb3b6c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1868,7 +1868,6 @@ void SurfaceFlinger::rebuildLayerStacks() { // can only be one of // - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced) // - Dataspace::DISPLAY_P3 -// - Dataspace::V0_SCRGB_LINEAR // The returned HDR data space is one of // - Dataspace::UNKNOWN // - Dataspace::BT2020_HLG @@ -1882,12 +1881,8 @@ Dataspace SurfaceFlinger::getBestDataspace( switch (layer->getDataSpace()) { case Dataspace::V0_SCRGB: case Dataspace::V0_SCRGB_LINEAR: - bestDataSpace = Dataspace::V0_SCRGB_LINEAR; - break; case Dataspace::DISPLAY_P3: - if (bestDataSpace == Dataspace::SRGB) { - bestDataSpace = Dataspace::DISPLAY_P3; - } + bestDataSpace = Dataspace::DISPLAY_P3; break; case Dataspace::BT2020_PQ: case Dataspace::BT2020_ITU_PQ: @@ -1923,104 +1918,17 @@ void SurfaceFlinger::pickColorMode(const sp& displayDevice, Dataspace hdrDataSpace; Dataspace bestDataSpace = getBestDataspace(displayDevice, &hdrDataSpace); - if (hdrDataSpace == Dataspace::BT2020_PQ) { - // Hardware composer can handle BT2100 ColorMode only when - // - colorimetrical tone mapping is supported, or - // - Auto mode is turned on and enhanced tone mapping is supported. - if (displayDevice->hasBT2100PQColorimetricSupport() || - (mDisplayColorSetting == DisplayColorSetting::ENHANCED && - displayDevice->hasBT2100PQEnhanceSupport())) { - *outMode = ColorMode::BT2100_PQ; - *outDataSpace = Dataspace::BT2020_PQ; - } else if (displayDevice->hasHDR10Support()) { - // Legacy HDR support. HDR layers are treated as UNKNOWN layers. - hdrDataSpace = Dataspace::UNKNOWN; - } else { - // Simulate PQ through RenderEngine, pick DISPLAY_P3 color mode. - *outMode = ColorMode::DISPLAY_P3; - *outDataSpace = Dataspace::DISPLAY_P3; - } - } else if (hdrDataSpace == Dataspace::BT2020_HLG) { - if (displayDevice->hasBT2100HLGColorimetricSupport() || - (mDisplayColorSetting == DisplayColorSetting::ENHANCED && - displayDevice->hasBT2100HLGEnhanceSupport())) { - *outMode = ColorMode::BT2100_HLG; - *outDataSpace = Dataspace::BT2020_HLG; - } else if (displayDevice->hasHLGSupport()) { - // Legacy HDR support. HDR layers are treated as UNKNOWN layers. - hdrDataSpace = Dataspace::UNKNOWN; - } else { - // Simulate HLG through RenderEngine, pick DISPLAY_P3 color mode. - *outMode = ColorMode::DISPLAY_P3; - *outDataSpace = Dataspace::DISPLAY_P3; - } - } + RenderIntent intent = mDisplayColorSetting == DisplayColorSetting::ENHANCED ? + RenderIntent::ENHANCE : RenderIntent::COLORIMETRIC; - // At this point, there's no HDR layer. - if (hdrDataSpace == Dataspace::UNKNOWN) { - switch (bestDataSpace) { - case Dataspace::DISPLAY_P3: - case Dataspace::V0_SCRGB_LINEAR: - *outMode = ColorMode::DISPLAY_P3; - *outDataSpace = Dataspace::DISPLAY_P3; - break; - default: - *outMode = ColorMode::SRGB; - *outDataSpace = Dataspace::SRGB; - break; - } + // respect hdrDataSpace only when there is modern HDR support + if (hdrDataSpace != Dataspace::UNKNOWN && displayDevice->hasModernHdrSupport(hdrDataSpace)) { + bestDataSpace = hdrDataSpace; + intent = mDisplayColorSetting == DisplayColorSetting::ENHANCED ? + RenderIntent::TONE_MAP_ENHANCE : RenderIntent::TONE_MAP_COLORIMETRIC; } - *outRenderIntent = pickRenderIntent(displayDevice, *outMode); -} -RenderIntent SurfaceFlinger::pickRenderIntent(const sp& displayDevice, - ColorMode colorMode) const { - // Native Mode means the display is not color managed, and whichever - // render intent is picked doesn't matter, thus return - // RenderIntent::COLORIMETRIC as default here. - if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) { - return RenderIntent::COLORIMETRIC; - } - - // In Auto Color Mode, we want to strech to panel color space, right now - // only the built-in display supports it. - if (mDisplayColorSetting == DisplayColorSetting::ENHANCED && - mBuiltinDisplaySupportsEnhance && - displayDevice->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) { - switch (colorMode) { - case ColorMode::DISPLAY_P3: - case ColorMode::SRGB: - return RenderIntent::ENHANCE; - // In Auto Color Mode, BT2100_PQ and BT2100_HLG will only be picked - // when TONE_MAP_ENHANCE or TONE_MAP_COLORIMETRIC is supported. - // If TONE_MAP_ENHANCE is not supported, fall back to TONE_MAP_COLORIMETRIC. - case ColorMode::BT2100_PQ: - return displayDevice->hasBT2100PQEnhanceSupport() ? - RenderIntent::TONE_MAP_ENHANCE : RenderIntent::TONE_MAP_COLORIMETRIC; - case ColorMode::BT2100_HLG: - return displayDevice->hasBT2100HLGEnhanceSupport() ? - RenderIntent::TONE_MAP_ENHANCE : RenderIntent::TONE_MAP_COLORIMETRIC; - // This statement shouldn't be reached, switch cases will always - // cover all possible ColorMode returned by pickColorMode. - default: - return RenderIntent::COLORIMETRIC; - } - } - - // Either enhance is not supported or we are in natural mode. - - // Natural Mode means it's color managed and the color must be right, - // thus we pick RenderIntent::COLORIMETRIC as render intent for non-HDR - // content and pick RenderIntent::TONE_MAP_COLORIMETRIC for HDR content. - switch (colorMode) { - // In Natural Color Mode, BT2100_PQ and BT2100_HLG will only be picked - // when TONE_MAP_COLORIMETRIC is supported. - case ColorMode::BT2100_PQ: - case ColorMode::BT2100_HLG: - return RenderIntent::TONE_MAP_COLORIMETRIC; - default: - return RenderIntent::COLORIMETRIC; - } + displayDevice->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); } void SurfaceFlinger::setUpHWComposer() { @@ -2332,7 +2240,7 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( const wp& display, int hwcId, const DisplayDeviceState& state, const sp& dispSurface, const sp& producer) { bool hasWideColorGamut = false; - std::unordered_map> hdrAndRenderIntents; + std::unordered_map> hwcColorModes; if (hasWideColorDisplay) { std::vector modes = getHwComposer().getColorModes(hwcId); @@ -2349,18 +2257,7 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( std::vector renderIntents = getHwComposer().getRenderIntents(hwcId, colorMode); - if (state.type == DisplayDevice::DISPLAY_PRIMARY) { - for (auto intent : renderIntents) { - if (intent == RenderIntent::ENHANCE) { - mBuiltinDisplaySupportsEnhance = true; - break; - } - } - } - - if (colorMode == ColorMode::BT2100_PQ || colorMode == ColorMode::BT2100_HLG) { - hdrAndRenderIntents.emplace(colorMode, renderIntents); - } + hwcColorModes.emplace(colorMode, renderIntents); } } @@ -2400,17 +2297,21 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( dispSurface, std::move(renderSurface), displayWidth, displayHeight, hasWideColorGamut, hdrCapabilities, getHwComposer().getSupportedPerFrameMetadata(hwcId), - hdrAndRenderIntents, initialPowerMode); + hwcColorModes, initialPowerMode); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); } + if (hw->isPrimary() && hw->hasRenderIntent(RenderIntent::ENHANCE)) { + mBuiltinDisplaySupportsEnhance = true; + } + ColorMode defaultColorMode = ColorMode::NATIVE; Dataspace defaultDataSpace = Dataspace::UNKNOWN; if (hasWideColorGamut) { defaultColorMode = ColorMode::SRGB; - defaultDataSpace = Dataspace::V0_SRGB; + defaultDataSpace = Dataspace::SRGB; } setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace, RenderIntent::COLORIMETRIC); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d9cf9461ca..f889beba8f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -664,8 +664,6 @@ private: ui::ColorMode* outMode, ui::Dataspace* outDataSpace, ui::RenderIntent* outRenderIntent) const; - ui::RenderIntent pickRenderIntent(const sp& displayDevice, - ui::ColorMode colorMode) const; void setUpHWComposer(); void doComposition(); -- cgit v1.2.3-59-g8ed1b From bbb44464990d0becd1c5eef77f85da82b8008534 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 21 May 2018 15:33:27 -0700 Subject: surfaceflinger: display color setting is a hint Display color setting is merely a hint. Check the active render intent before applying the legacy sRGB color matrix. Bug: 79843697 Test: manual Change-Id: I73b45cbf2274a56037ce0439470f1baafffa8914 --- services/surfaceflinger/SurfaceFlinger.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e7e3eb3b6c..fe9a1d0ac1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2898,9 +2898,10 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev getRenderEngine().setupColorTransform(mDrawingState.colorMatrix); } - needsLegacyColorMatrix = (mDisplayColorSetting == DisplayColorSetting::ENHANCED && - outputDataspace != Dataspace::UNKNOWN && - outputDataspace != Dataspace::SRGB); + needsLegacyColorMatrix = + (displayDevice->getActiveRenderIntent() == RenderIntent::ENHANCE && + outputDataspace != Dataspace::UNKNOWN && + outputDataspace != Dataspace::SRGB); if (!displayDevice->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", -- cgit v1.2.3-59-g8ed1b From 0d711268fe57b73a38ec3590b6e67f03ff789fa1 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 21 May 2018 15:19:35 -0700 Subject: surfaceflinger: allow unknown render intents Allow render intents that are unknown to SurfaceFlinger. Bug: 79843697 Bug: 75981986 Test: manual Change-Id: Ia81436747b1d2fe9f44e749b93a9c1a5a7f1f6cb --- services/surfaceflinger/DisplayDevice.cpp | 12 +++- services/surfaceflinger/SurfaceFlinger.cpp | 90 ++++++++++++++---------------- services/surfaceflinger/SurfaceFlinger.h | 1 - 3 files changed, 53 insertions(+), 50 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index ccd2aba728..bacee209f5 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -708,8 +708,18 @@ void DisplayDevice::populateColorModes( return; } + // collect all known SDR render intents + std::unordered_set sdrRenderIntents(sSdrRenderIntents.begin(), + sSdrRenderIntents.end()); + auto iter = hwcColorModes.find(ColorMode::SRGB); + if (iter != hwcColorModes.end()) { + for (auto intent : iter->second) { + sdrRenderIntents.insert(intent); + } + } + // add known SDR combinations - for (auto intent : sSdrRenderIntents) { + for (auto intent : sdrRenderIntents) { for (auto mode : sSdrColorModes) { addColorMode(hwcColorModes, mode, intent); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index fe9a1d0ac1..4c695c4407 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -158,29 +158,18 @@ bool useTrebleTestingOverride() { return std::string(value) == "true"; } -DisplayColorSetting toDisplayColorSetting(int value) { - switch(value) { - case 0: - return DisplayColorSetting::MANAGED; - case 1: - return DisplayColorSetting::UNMANAGED; - case 2: - return DisplayColorSetting::ENHANCED; - default: - return DisplayColorSetting::MANAGED; - } -} - std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) { switch(displayColorSetting) { case DisplayColorSetting::MANAGED: - return std::string("Natural Mode"); + return std::string("Managed"); case DisplayColorSetting::UNMANAGED: - return std::string("Saturated Mode"); + return std::string("Unmanaged"); case DisplayColorSetting::ENHANCED: - return std::string("Auto Color Mode"); + return std::string("Enhanced"); + default: + return std::string("Unknown ") + + std::to_string(static_cast(displayColorSetting)); } - return std::string("Unknown Display Color Setting"); } NativeWindowSurface::~NativeWindowSurface() = default; @@ -738,9 +727,7 @@ void SurfaceFlinger::readPersistentProperties() { ALOGV("Saturation is set to %.2f", mGlobalSaturationFactor); property_get("persist.sys.sf.native_mode", value, "0"); - mDisplayColorSetting = toDisplayColorSetting(atoi(value)); - ALOGV("Display Color Setting is set to %s.", - decodeDisplayColorSetting(mDisplayColorSetting).c_str()); + mDisplayColorSetting = static_cast(atoi(value)); } void SurfaceFlinger::startBootAnim() { @@ -1918,8 +1905,19 @@ void SurfaceFlinger::pickColorMode(const sp& displayDevice, Dataspace hdrDataSpace; Dataspace bestDataSpace = getBestDataspace(displayDevice, &hdrDataSpace); - RenderIntent intent = mDisplayColorSetting == DisplayColorSetting::ENHANCED ? - RenderIntent::ENHANCE : RenderIntent::COLORIMETRIC; + RenderIntent intent; + switch (mDisplayColorSetting) { + case DisplayColorSetting::MANAGED: + case DisplayColorSetting::UNMANAGED: + intent = RenderIntent::COLORIMETRIC; + break; + case DisplayColorSetting::ENHANCED: + intent = RenderIntent::ENHANCE; + break; + default: // vendor display color setting + intent = static_cast(mDisplayColorSetting); + break; + } // respect hdrDataSpace only when there is modern HDR support if (hdrDataSpace != Dataspace::UNKNOWN && displayDevice->hasModernHdrSupport(hdrDataSpace)) { @@ -2303,10 +2301,6 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( nativeWindowSurface->preallocateBuffers(); } - if (hw->isPrimary() && hw->hasRenderIntent(RenderIntent::ENHANCE)) { - mBuiltinDisplaySupportsEnhance = true; - } - ColorMode defaultColorMode = ColorMode::NATIVE; Dataspace defaultDataSpace = Dataspace::UNKNOWN; if (hasWideColorGamut) { @@ -2899,7 +2893,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDev } needsLegacyColorMatrix = - (displayDevice->getActiveRenderIntent() == RenderIntent::ENHANCE && + (displayDevice->getActiveRenderIntent() >= RenderIntent::ENHANCE && outputDataspace != Dataspace::UNKNOWN && outputDataspace != Dataspace::SRGB); @@ -4073,7 +4067,8 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const { void SurfaceFlinger::dumpWideColorInfo(String8& result) const { result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay); - result.appendFormat("DisplayColorSetting: %d\n", mDisplayColorSetting); + result.appendFormat("DisplayColorSetting: %s\n", + decodeDisplayColorSetting(mDisplayColorSetting).c_str()); // TODO: print out if wide-color mode is active or not @@ -4601,15 +4596,7 @@ status_t SurfaceFlinger::onTransact( return NO_ERROR; } case 1023: { // Set native mode - int32_t value = data.readInt32(); - if (value > 2) { - return BAD_VALUE; - } - if (value == 2 && !mBuiltinDisplaySupportsEnhance) { - return BAD_VALUE; - } - - mDisplayColorSetting = toDisplayColorSetting(value); + mDisplayColorSetting = static_cast(data.readInt32()); invalidateHwcGeometry(); repaintEverything(); return NO_ERROR; @@ -4638,20 +4625,27 @@ status_t SurfaceFlinger::onTransact( } // Is a DisplayColorSetting supported? case 1027: { - int32_t value = data.readInt32(); - switch (value) { - case 0: + sp hw(getDefaultDisplayDevice()); + if (!hw) { + return NAME_NOT_FOUND; + } + + DisplayColorSetting setting = static_cast(data.readInt32()); + switch (setting) { + case DisplayColorSetting::MANAGED: reply->writeBool(hasWideColorDisplay); - return NO_ERROR; - case 1: + break; + case DisplayColorSetting::UNMANAGED: reply->writeBool(true); - return NO_ERROR; - case 2: - reply->writeBool(mBuiltinDisplaySupportsEnhance); - return NO_ERROR; - default: - return BAD_VALUE; + break; + case DisplayColorSetting::ENHANCED: + reply->writeBool(hw->hasRenderIntent(RenderIntent::ENHANCE)); + break; + default: // vendor display color setting + reply->writeBool(hw->hasRenderIntent(static_cast(setting))); + break; } + return NO_ERROR; } } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f889beba8f..fcfc54f153 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -878,7 +878,6 @@ private: DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::MANAGED; // Applied on sRGB layers when the render intent is non-colorimetric. mat4 mLegacySrgbSaturationMatrix; - bool mBuiltinDisplaySupportsEnhance = false; using CreateBufferQueueFunction = std::function* /* outProducer */, -- cgit v1.2.3-59-g8ed1b From 7501ed66a05f530062925011d1342e8651216051 Mon Sep 17 00:00:00 2001 From: Iris Chang Date: Mon, 30 Apr 2018 14:45:42 +0800 Subject: Need GSI to support landscape LCM When device uses landscape LCM, the nature of the screen shows that the device is a portrait device. After we flash with GSI, there is vendor solution for landscape LCM used at portrait device. As the result, the screen displays landscape layout and orientation while device is at portrait orientation. In addition, the sensor coordinate system mismatches with android coordinate system. We suggest Google can add config to handle the case "portrait device uses landscape LCM or landscape device uses portrait LCM". Bug: 69691076 Test: We verified following test cases for this patch on Android O-MR1. 1. Make sure homescreen is normal 2. Rotate device and make sure screen is normal 3. Grab screen shot and check if screen shot is normal 4. Connect to Wi-Fi display and make sure WFD screen is normal Test: Tested 1, 2 and 3 on Pixel 2. Test: artifially setup 90 degree rotation on Pixel and make sure that screenshots are aligned to the screen. Change-Id: Ib42c9a216e8a6fe465139d6eece152fb1765b422 --- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/DisplayDevice.cpp | 9 +++ services/surfaceflinger/RenderArea.cpp | 10 +++- services/surfaceflinger/RenderArea.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 88 ++++++++++++++++++++++++++++-- services/surfaceflinger/SurfaceFlinger.h | 3 + 6 files changed, 106 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 6a69844d9f..c2bb6ad6b4 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -22,6 +22,7 @@ cc_defaults { "android.frameworks.vr.composer@1.0", "android.hardware.configstore-utils", "android.hardware.configstore@1.0", + "android.hardware.configstore@1.1", "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 2b1e5775ba..48a56bf7e7 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -475,6 +475,15 @@ void DisplayDevice::setProjection(int orientation, TL.set(-src_x, -src_y); TP.set(dst_x, dst_y); + // need to take care of primary display rotation for mGlobalTransform + // for case if the panel is not installed aligned with device orientation + if (mType == DisplayType::DISPLAY_PRIMARY) { + int primaryDisplayOrientation = mFlinger->getPrimaryDisplayOrientation(); + DisplayDevice::orientationToTransfrom( + (orientation + primaryDisplayOrientation) % (DisplayState::eOrientation270 + 1), + w, h, &R); + } + // The viewport and frame are both in the logical orientation. // Apply the logical translation, scale to physical size, apply the // physical translation and finally rotate to the physical orientation. diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp index 46ec8e68ba..1a8edf3e79 100644 --- a/services/surfaceflinger/RenderArea.cpp +++ b/services/surfaceflinger/RenderArea.cpp @@ -1,5 +1,7 @@ #include "RenderArea.h" +#include + namespace android { float RenderArea::getCaptureFillValue(CaptureFill captureFill) { @@ -15,7 +17,7 @@ float RenderArea::getCaptureFillValue(CaptureFill captureFill) { * Checks that the requested width and height are valid and updates them to the render area * dimensions if they are set to 0 */ -status_t RenderArea::updateDimensions() { +status_t RenderArea::updateDimensions(int displayRotation) { // get screen geometry uint32_t width = getWidth(); @@ -25,6 +27,10 @@ status_t RenderArea::updateDimensions() { std::swap(width, height); } + if (displayRotation & DisplayState::eOrientationSwapMask) { + std::swap(width, height); + } + if ((mReqWidth > width) || (mReqHeight > height)) { ALOGE("size mismatch (%d, %d) > (%d, %d)", mReqWidth, mReqHeight, width, height); return BAD_VALUE; @@ -40,4 +46,4 @@ status_t RenderArea::updateDimensions() { return NO_ERROR; } -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 938c3ce0dd..96e4b5f48b 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -36,7 +36,7 @@ public: int getReqHeight() const { return mReqHeight; }; int getReqWidth() const { return mReqWidth; }; Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; - status_t updateDimensions(); + status_t updateDimensions(int displayRotation); CaptureFill getCaptureFill() const { return mCaptureFill; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9117207544..6f3f2520ce 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -88,6 +88,8 @@ #include #include +#include +#include #include #include @@ -282,6 +284,26 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { hasWideColorDisplay = getBool(false); + V1_1::DisplayOrientation primaryDisplayOrientation = + getDisplayOrientation< V1_1::ISurfaceFlingerConfigs, &V1_1::ISurfaceFlingerConfigs::primaryDisplayOrientation>( + V1_1::DisplayOrientation::ORIENTATION_0); + + switch (primaryDisplayOrientation) { + case V1_1::DisplayOrientation::ORIENTATION_90: + mPrimaryDisplayOrientation = DisplayState::eOrientation90; + break; + case V1_1::DisplayOrientation::ORIENTATION_180: + mPrimaryDisplayOrientation = DisplayState::eOrientation180; + break; + case V1_1::DisplayOrientation::ORIENTATION_270: + mPrimaryDisplayOrientation = DisplayState::eOrientation270; + break; + default: + mPrimaryDisplayOrientation = DisplayState::eOrientationDefault; + break; + } + ALOGV("Primary Display Orientation is set to %2d.", mPrimaryDisplayOrientation); + mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset); // debugging stuff... @@ -895,6 +917,11 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, // All non-virtual displays are currently considered secure. info.secure = true; + if (type == DisplayDevice::DISPLAY_PRIMARY && + mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) { + std::swap(info.w, info.h); + } + configs->push_back(info); } @@ -4913,7 +4940,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, bool useIdentityTransform) { ATRACE_CALL(); - renderArea.updateDimensions(); + renderArea.updateDimensions(mPrimaryDisplayOrientation); const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; @@ -4997,13 +5024,35 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, const auto reqHeight = renderArea.getReqHeight(); Rect sourceCrop = renderArea.getSourceCrop(); - const bool filtering = static_cast(reqWidth) != raWidth || - static_cast(reqHeight) != raHeight; + bool filtering = false; + if (mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) { + filtering = static_cast(reqWidth) != raHeight || + static_cast(reqHeight) != raWidth; + } else { + filtering = static_cast(reqWidth) != raWidth || + static_cast(reqHeight) != raHeight; + } // if a default or invalid sourceCrop is passed in, set reasonable values if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || !sourceCrop.isValid()) { sourceCrop.setLeftTop(Point(0, 0)); sourceCrop.setRightBottom(Point(raWidth, raHeight)); + } else if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) { + Transform tr; + uint32_t flags = 0x00; + switch (mPrimaryDisplayOrientation) { + case DisplayState::eOrientation90: + flags = Transform::ROT_90; + break; + case DisplayState::eOrientation180: + flags = Transform::ROT_180; + break; + case DisplayState::eOrientation270: + flags = Transform::ROT_270; + break; + } + tr.set(flags, raWidth, raHeight); + sourceCrop = tr.transform(sourceCrop); } // ensure that sourceCrop is inside screen @@ -5027,9 +5076,40 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, // make sure to clear all GL error flags engine.checkErrors(); + Transform::orientation_flags rotation = renderArea.getRotationFlags(); + if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) { + // convert hw orientation into flag presentation + // here inverse transform needed + uint8_t hw_rot_90 = 0x00; + uint8_t hw_flip_hv = 0x00; + switch (mPrimaryDisplayOrientation) { + case DisplayState::eOrientation90: + hw_rot_90 = Transform::ROT_90; + hw_flip_hv = Transform::ROT_180; + break; + case DisplayState::eOrientation180: + hw_flip_hv = Transform::ROT_180; + break; + case DisplayState::eOrientation270: + hw_rot_90 = Transform::ROT_90; + break; + } + + // transform flags operation + // 1) flip H V if both have ROT_90 flag + // 2) XOR these flags + uint8_t rotation_rot_90 = rotation & Transform::ROT_90; + uint8_t rotation_flip_hv = rotation & Transform::ROT_180; + if (rotation_rot_90 & hw_rot_90) { + rotation_flip_hv = (~rotation_flip_hv) & Transform::ROT_180; + } + rotation = static_cast + ((rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv)); + } + // set-up our viewport engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, raHeight, yswap, - renderArea.getRotationFlags()); + rotation); engine.disableTexturing(); const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill()); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d9cf9461ca..c5a676bab4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -341,6 +341,8 @@ public: bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; + int getPrimaryDisplayOrientation() const { return mPrimaryDisplayOrientation; } + private: friend class Client; friend class DisplayEventConnection; @@ -845,6 +847,7 @@ private: mutable std::unique_ptr mEventQueue{std::make_unique()}; FrameTracker mAnimFrameTracker; DispSync mPrimaryDispSync; + int mPrimaryDisplayOrientation = DisplayState::eOrientationDefault; // protected by mDestroyedLayerLock; mutable Mutex mDestroyedLayerLock; -- cgit v1.2.3-59-g8ed1b From 9053521815dc4cbe3d2ab21096e05d33386dd5da Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Wed, 23 May 2018 23:44:06 +0200 Subject: Keep early vsync-offsets for at least two frames after transaction Imagine the following sequence, in which vsync-sf is usually 4ms behind vsync-app. - Vsync-app fires. The app sends a transaction with early wakeup. - Vsync-sf fires immediately after early wakeup is received, before the regular 4ms delay. - Vsync-sf resets itself to vsync-app+4ms as the transaction was handled. - Repeat 1, but now the app was a bit delayed and sends the early wakeup late, such that the time used to do GL comp isn't enough to avoid jank. To fix this, we apply a low pass filter for transaction-caused early wake and keep it early for at least 2 frames. Test: Open/close apps, inspect systraces and verify wake-up times Bug: 78611607 Change-Id: I74b0d88a4d95ca5b6d24950e14e3d6a9379f2714 --- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- services/surfaceflinger/VSyncModulator.h | 36 +++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9117207544..a73ac12ff3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1535,7 +1535,7 @@ void SurfaceFlinger::handleMessageRefresh() { mHadClientComposition = mHadClientComposition || getBE().mHwc->hasClientComposition(displayDevice->getHwcDisplayId()); } - mVsyncModulator.setLastFrameUsedRenderEngine(mHadClientComposition); + mVsyncModulator.onRefreshed(mHadClientComposition); mLayersWithQueuedFrames.clear(); } diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/VSyncModulator.h index 3e5800e2a2..d526313994 100644 --- a/services/surfaceflinger/VSyncModulator.h +++ b/services/surfaceflinger/VSyncModulator.h @@ -28,6 +28,12 @@ namespace android { * Modulates the vsync-offsets depending on current SurfaceFlinger state. */ class VSyncModulator { +private: + + // Number of frames we'll keep the early phase offsets once they are activated. This acts as a + // low-pass filter in case the client isn't quick enough in sending new transactions. + const int MIN_EARLY_FRAME_COUNT = 2; + public: enum TransactionStart { @@ -55,6 +61,11 @@ public: } void setTransactionStart(TransactionStart transactionStart) { + + if (transactionStart == TransactionStart::EARLY) { + mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT; + } + // An early transaction stays an early transaction. if (transactionStart == mTransactionStart || mTransactionStart == TransactionStart::EARLY) { return; @@ -69,10 +80,19 @@ public: updatePhaseOffsets(); } - void setLastFrameUsedRenderEngine(bool re) { - if (re == mLastFrameUsedRenderEngine) return; - mLastFrameUsedRenderEngine = re; - updatePhaseOffsets(); + void onRefreshed(bool usedRenderEngine) { + bool updatePhaseOffsetsNeeded = false; + if (mRemainingEarlyFrameCount > 0) { + mRemainingEarlyFrameCount--; + updatePhaseOffsetsNeeded = true; + } + if (usedRenderEngine != mLastFrameUsedRenderEngine) { + mLastFrameUsedRenderEngine = usedRenderEngine; + updatePhaseOffsetsNeeded = true; + } + if (updatePhaseOffsetsNeeded) { + updatePhaseOffsets(); + } } private: @@ -82,7 +102,7 @@ private: // Do not change phase offsets if disabled. if (mEarlyPhaseOffset == mLatePhaseOffset) return; - if (mTransactionStart == TransactionStart::EARLY || mLastFrameUsedRenderEngine) { + if (shouldUseEarlyOffset()) { if (mPhaseOffset != mEarlyPhaseOffset) { if (mEventThread) { mEventThread->setPhaseOffset(mEarlyPhaseOffset); @@ -99,12 +119,18 @@ private: } } + bool shouldUseEarlyOffset() { + return mTransactionStart == TransactionStart::EARLY || mLastFrameUsedRenderEngine + || mRemainingEarlyFrameCount > 0; + } + nsecs_t mLatePhaseOffset = 0; nsecs_t mEarlyPhaseOffset = 0; EventThread* mEventThread = nullptr; std::atomic mPhaseOffset = 0; std::atomic mTransactionStart = TransactionStart::NORMAL; std::atomic mLastFrameUsedRenderEngine = false; + std::atomic mRemainingEarlyFrameCount = 0; }; } // namespace android -- cgit v1.2.3-59-g8ed1b From c4b08bde2aaa455a7f789eb2858863d19563b949 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 29 May 2018 12:57:23 -0700 Subject: surfaceflinger: RenderIntent::COLORIMETRIC is no longer mandatory RenderIntent::COLORIMETRIC is mandatory only for SDR color modes. For HDR color modes, RenderIntent::TONE_MAP_COLORIMETRIC is mandatory. Bug: 80030364 Test: HDR videos Change-Id: I70d96ac66d069218d789dded330169284a61bde1 --- services/surfaceflinger/DisplayDevice.cpp | 28 ++++++++++++++++++++-------- services/surfaceflinger/SurfaceFlinger.cpp | 18 +++++++++--------- 2 files changed, 29 insertions(+), 17 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index e81df8ad53..9ecbacc86b 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -162,18 +162,20 @@ std::vector getRenderIntentCandidates(RenderIntent intent) { } } - // add other HDR candidates when intent is HDR if (isHdr) { + // add other HDR candidates when intent is HDR for (auto hdrIntent : sHdrRenderIntents) { if (hdrIntent != intent) { candidates.push_back(hdrIntent); } } - } - - // add COLORIMETRIC - if (intent != RenderIntent::COLORIMETRIC) { - candidates.push_back(RenderIntent::COLORIMETRIC); + } else { + // add other SDR candidates when intent is SDR + for (auto sdrIntent : sSdrRenderIntents) { + if (sdrIntent != intent) { + candidates.push_back(sdrIntent); + } + } } return candidates; @@ -727,14 +729,24 @@ void DisplayDevice::populateColorModes( } } - // add known SDR combinations + // add all known SDR combinations for (auto intent : sdrRenderIntents) { for (auto mode : sSdrColorModes) { addColorMode(hwcColorModes, mode, intent); } } - // add known HDR combinations + // collect all known HDR render intents + std::unordered_set hdrRenderIntents(sHdrRenderIntents.begin(), + sHdrRenderIntents.end()); + iter = hwcColorModes.find(ColorMode::BT2100_PQ); + if (iter != hwcColorModes.end()) { + for (auto intent : iter->second) { + hdrRenderIntents.insert(intent); + } + } + + // add all known HDR combinations for (auto intent : sHdrRenderIntents) { for (auto mode : sHdrColorModes) { addColorMode(hwcColorModes, mode, intent); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f5fa478a2d..a120738713 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1932,27 +1932,27 @@ void SurfaceFlinger::pickColorMode(const sp& displayDevice, Dataspace hdrDataSpace; Dataspace bestDataSpace = getBestDataspace(displayDevice, &hdrDataSpace); + // respect hdrDataSpace only when there is modern HDR support + const bool isHdr = hdrDataSpace != Dataspace::UNKNOWN && + displayDevice->hasModernHdrSupport(hdrDataSpace); + if (isHdr) { + bestDataSpace = hdrDataSpace; + } + RenderIntent intent; switch (mDisplayColorSetting) { case DisplayColorSetting::MANAGED: case DisplayColorSetting::UNMANAGED: - intent = RenderIntent::COLORIMETRIC; + intent = isHdr ? RenderIntent::TONE_MAP_COLORIMETRIC : RenderIntent::COLORIMETRIC; break; case DisplayColorSetting::ENHANCED: - intent = RenderIntent::ENHANCE; + intent = isHdr ? RenderIntent::TONE_MAP_ENHANCE : RenderIntent::ENHANCE; break; default: // vendor display color setting intent = static_cast(mDisplayColorSetting); break; } - // respect hdrDataSpace only when there is modern HDR support - if (hdrDataSpace != Dataspace::UNKNOWN && displayDevice->hasModernHdrSupport(hdrDataSpace)) { - bestDataSpace = hdrDataSpace; - intent = mDisplayColorSetting == DisplayColorSetting::ENHANCED ? - RenderIntent::TONE_MAP_ENHANCE : RenderIntent::TONE_MAP_COLORIMETRIC; - } - displayDevice->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); } -- cgit v1.2.3-59-g8ed1b From dba3273a27fb90f19a73abe7142790ad21387484 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Mon, 28 May 2018 17:43:52 +0200 Subject: Push existing pending state when deferring transaction Otherwise the information from another transaction that happened before deferring the transaction could have been deferred as well. To fix that, we push the currently pending state if the transaction is deferred. Furthermore, we need to modify the behavior how flags are applied. Imagine the following sequence of events - Surface is hidden flags=hidden - t1 doesn't modify the flags (0/0) but sets some other properties. flags=hidden mask=0. mCurrentState gets pushed onto mPendingState before t2 sets (0/hidden) (flags/mask) flags=0 mask=hidden, to show the surface. Furthemore, we defer this transaction. mCurrentState gets pushed onto mPendingState. - At this point, mCurrentState.flags = 0 (shown), but mDrawingState.flags = hidden - doTransaction happens. c (the state to promote to drawing state) = mCurrentState => c.flags = 0 (shown) Since t1 isn't deferred, the 0th element of mPendingState gets popped and applied to c. Since mask=0, c.flags = 0 still. - c gets promoted to mDrawingState and BOOM the surface was shown even though the barrier of the transaction showing hasn't opened yet. Looking closer at the logic it makes sense to just apply the mask when modifying the current state, and then just pushing it like all other attributes. Test: go/wm-smoke Bug: 78611607 Change-Id: Ia100532189ef7f59f8939c59db9b6292b41e8e77 --- services/surfaceflinger/Layer.cpp | 4 ---- services/surfaceflinger/Layer.h | 3 +-- services/surfaceflinger/SurfaceFlinger.cpp | 7 +++++++ 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b94af77967..83d08a2322 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -920,10 +920,7 @@ void Layer::pushPendingState() { } void Layer::popPendingState(State* stateToCommit) { - auto oldFlags = stateToCommit->flags; *stateToCommit = mPendingStates[0]; - stateToCommit->flags = - (oldFlags & ~stateToCommit->mask) | (stateToCommit->flags & stateToCommit->mask); mPendingStates.removeAt(0); ATRACE_INT(mTransactionName.string(), mPendingStates.size()); @@ -1270,7 +1267,6 @@ bool Layer::setFlags(uint8_t flags, uint8_t mask) { if (mCurrentState.flags == newFlags) return false; mCurrentState.sequence++; mCurrentState.flags = newFlags; - mCurrentState.mask = mask; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 7342c8b987..ae80043a5d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -186,7 +186,6 @@ public: uint32_t layerStack; uint8_t flags; - uint8_t mask; uint8_t reserved[2]; int32_t sequence; // changes when visible regions can change bool modified; @@ -588,6 +587,7 @@ public: // SurfaceFlinger to complete a transaction. void commitChildList(); int32_t getZ() const; + void pushPendingState(); protected: // constant @@ -670,7 +670,6 @@ protected: // Returns false if the relevant frame has already been latched bool addSyncPoint(const std::shared_ptr& point); - void pushPendingState(); void popPendingState(State* stateToCommit); bool applyPendingStates(State* stateToCommit); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a120738713..730bdcd917 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3345,6 +3345,13 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState const uint32_t what = s.what; bool geometryAppliesWithResize = what & layer_state_t::eGeometryAppliesWithResize; + + // If we are deferring transaction, make sure to push the pending state, as otherwise the + // pending state will also be deferred. + if (what & layer_state_t::eDeferTransaction) { + layer->pushPendingState(); + } + if (what & layer_state_t::ePositionChanged) { if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) { flags |= eTraversalNeeded; -- cgit v1.2.3-59-g8ed1b From 3c6b7efc5204eab5701d5ab2f0ff87763cc322fa Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 5 Jun 2018 10:58:41 -0700 Subject: [SurfaceFlinger] Respect HDR data space. Respect HDR data space when there is no legacy HDR support. Previously we only cared about HDR data space when it is supported, however, on Pixel 2 there is no HDR mode support. This patch makes sure that when HDR mode is not supported, we fall back to Display P3 color mode correctly. BUG: 80404330 Test: Build, flash and watch Youtube HDR Change-Id: I7d27711fe4d33268e5ebbd14fce0975f9e642e84 Merged-In: I7d27711fe4d33268e5ebbd14fce0975f9e642e84 --- services/surfaceflinger/DisplayDevice.cpp | 4 ++-- services/surfaceflinger/DisplayDevice.h | 6 +++--- services/surfaceflinger/SurfaceFlinger.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 9ecbacc86b..db095a51d9 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -761,12 +761,12 @@ bool DisplayDevice::hasRenderIntent(RenderIntent intent) const { return iter != mColorModes.end() && iter->second.renderIntent == intent; } -bool DisplayDevice::hasModernHdrSupport(Dataspace dataspace) const { +bool DisplayDevice::hasLegacyHdrSupport(Dataspace dataspace) const { if ((dataspace == Dataspace::BT2020_PQ && hasHDR10Support()) || (dataspace == Dataspace::BT2020_HLG && hasHLGSupport())) { auto iter = mColorModes.find(getColorModeKey(dataspace, RenderIntent::TONE_MAP_COLORIMETRIC)); - return iter != mColorModes.end() && iter->second.dataspace == dataspace; + return iter == mColorModes.end() || iter->second.dataspace != dataspace; } return false; diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index b3859b6793..6c3bd91793 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -150,9 +150,9 @@ public: bool hasHLGSupport() const { return mHasHLG; } bool hasDolbyVisionSupport() const { return mHasDolbyVision; } - // Return true if the corresponding color mode for the HDR dataspace is - // supported. - bool hasModernHdrSupport(ui::Dataspace dataspace) const; + // Return true if the HDR dataspace is supported but + // there is no corresponding color mode. + bool hasLegacyHdrSupport(ui::Dataspace dataspace) const; // The returned HdrCapabilities is the combination of HDR capabilities from // hardware composer and RenderEngine. When the DisplayDevice supports wide diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 97edd357ed..cdd9c1804f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1932,9 +1932,9 @@ void SurfaceFlinger::pickColorMode(const sp& displayDevice, Dataspace hdrDataSpace; Dataspace bestDataSpace = getBestDataspace(displayDevice, &hdrDataSpace); - // respect hdrDataSpace only when there is modern HDR support + // respect hdrDataSpace only when there is no legacy HDR support const bool isHdr = hdrDataSpace != Dataspace::UNKNOWN && - displayDevice->hasModernHdrSupport(hdrDataSpace); + !displayDevice->hasLegacyHdrSupport(hdrDataSpace); if (isHdr) { bestDataSpace = hdrDataSpace; } -- cgit v1.2.3-59-g8ed1b From 07376a98a6c66c4e48bdebe82616f0ae47e5f805 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Tue, 5 Jun 2018 15:46:58 -0700 Subject: surfaceflinger: force client composition for Y410 When the pixel format is Y410 masquerading as RGBA_1010102, always force client composition. Bug: 80509363 Test: no effect on Pixel devices Change-Id: I31996eeda1559b0557a5acb53d593fd4f395ccaf Merged-In: I31996eeda1559b0557a5acb53d593fd4f395ccaf --- services/surfaceflinger/BufferLayer.cpp | 11 ++++++++--- services/surfaceflinger/BufferLayer.h | 2 ++ services/surfaceflinger/Layer.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 11 ++++++----- 4 files changed, 18 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 17ed9aa00c..fda7906744 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -815,6 +815,13 @@ bool BufferLayer::getOpacityForFormat(uint32_t format) { return true; } +bool BufferLayer::isHdrY410() const { + // pixel format is HDR Y410 masquerading as RGBA_1010102 + return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && + mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA && + getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); +} + void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { ATRACE_CALL(); const State& s(getDrawingState()); @@ -868,9 +875,7 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT getColor()); engine.setSourceDataSpace(mCurrentDataSpace); - if (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && - mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA && - getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) { + if (isHdrY410()) { engine.setSourceY410BT2020(true); } diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 6b02f8c128..bf0ca69253 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -129,6 +129,8 @@ public: bool isBufferLatched() const override { return mRefreshPending; } void setDefaultBufferSize(uint32_t w, uint32_t h) override; + bool isHdrY410() const override; + void setPerFrameData(const sp& displayDevice) override; bool isOpaque(const Layer::State& s) const override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ae80043a5d..34811fb152 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -378,6 +378,8 @@ protected: public: virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {} + virtual bool isHdrY410() const { return false; } + void setGeometry(const sp& displayDevice, uint32_t z); void forceClientComposition(int32_t hwcId); bool getForceClientComposition(int32_t hwcId); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 97edd357ed..c97ae19315 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2031,13 +2031,14 @@ void SurfaceFlinger::setUpHWComposer() { "display %zd: %d", displayId, result); } for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - if ((layer->getDataSpace() == Dataspace::BT2020_PQ || - layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && + if (layer->isHdrY410()) { + layer->forceClientComposition(hwcId); + } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ || + layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && !displayDevice->hasHDR10Support()) { layer->forceClientComposition(hwcId); - } - if ((layer->getDataSpace() == Dataspace::BT2020_HLG || - layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && + } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG || + layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && !displayDevice->hasHLGSupport()) { layer->forceClientComposition(hwcId); } -- cgit v1.2.3-59-g8ed1b