From 161410b01a37bcc5522d8e91fe0a743989c86e70 Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 27 Jul 2017 10:46:08 -0700 Subject: Only detach children from a different client than parent. The purpose of detach is prevent another client from modifying the layer. Therefore, layers with the same client as their parent shouldn't be detached because the parent can and should be able to still modify those layers. Test: Updated Transaction_test so it has a test when the parent detaches children with same client and detaches children with different client. Change-Id: Ieede3c7b472e6eaa567163876b71cc9d7e889daf --- services/surfaceflinger/Layer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b14fd7bb87..1903bb1a0d 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2591,8 +2591,9 @@ bool Layer::detachChildren() { return; } + sp parentClient = mClientRef.promote(); sp client(child->mClientRef.promote()); - if (client != nullptr) { + if (client != nullptr && parentClient != client) { client->detachLayer(child); } }); -- cgit v1.2.3-59-g8ed1b From 94e35b93537c7f9da018688ac8a8ba87f4689915 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 --- 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/Layer.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 4154d6a87f..9dfdaa1d99 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -77,6 +77,7 @@ #include "MonitoredProducer.h" #include "SurfaceFlinger.h" +#include "DisplayHardware/ComposerHal.h" #include "DisplayHardware/FramebufferSurface.h" #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/VirtualDisplaySurface.h" @@ -101,10 +102,24 @@ EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint na namespace android { - using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +namespace { +class ConditionalLock { +public: + ConditionalLock(Mutex& mutex, bool lock) : mMutex(mutex), mLocked(lock) { + if (lock) { + mMutex.lock(); + } + } + ~ConditionalLock() { if (mLocked) mMutex.unlock(); } +private: + Mutex& mMutex; + bool mLocked; +}; +} // namespace anonymous + // --------------------------------------------------------------------------- const String16 sHardwareTest("android.permission.HARDWARE_TEST"); @@ -147,9 +162,6 @@ SurfaceFlinger::SurfaceFlinger() mLayersRemoved(false), mLayersAdded(false), mRepaintEverything(0), - mHwc(nullptr), - mRealHwc(nullptr), - mVrHwc(nullptr), mHwcServiceName(getHwcServiceName()), mRenderEngine(nullptr), mBootTime(systemTime()), @@ -177,7 +189,9 @@ SurfaceFlinger::SurfaceFlinger() mTotalTime(0), mLastSwapTime(0), mNumLayers(0), - mVrFlingerRequestsDisplay(false) + mVrFlingerRequestsDisplay(false), + mMainThreadId(std::this_thread::get_id()), + mComposerSequenceId(0) { ALOGI("SurfaceFlinger is starting"); @@ -583,48 +597,46 @@ void SurfaceFlinger::init() { ALOGI("Phase offset NS: %" PRId64 "", vsyncPhaseOffsetNs); - { // Autolock scope - Mutex::Autolock _l(mStateLock); + Mutex::Autolock _l(mStateLock); - // initialize EGL for the default display - mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(mEGLDisplay, NULL, NULL); - - // start the EventThread - sp 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/Layer.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 8c3b6ac2012ad6731f214fca6fea73fd13619d0c Mon Sep 17 00:00:00 2001 From: John Reck Date: Thu, 24 Aug 2017 10:25:42 -0700 Subject: Fix layer Z dump %u -> %d to match that Z is an int32_t Test: manual Change-Id: Ia7f1f3575953e63eeb77a2f776142007f23ad1a4 --- services/surfaceflinger/Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e92565fd9c..1355a44d3b 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2501,7 +2501,7 @@ void Layer::miniDump(String8& result, int32_t hwcId) const { const Layer::State& layerState(getDrawingState()); const HWCInfo& hwcInfo = mHwcLayers.at(hwcId); - result.appendFormat(" %10u | ", layerState.z); + result.appendFormat(" %10d | ", layerState.z); result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str()); const Rect& frame = hwcInfo.displayFrame; -- cgit v1.2.3-59-g8ed1b From e392b55de711657d2a955b9785588d009b5e922d Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 19 Sep 2017 12:16:05 -0700 Subject: SurfaceFlinger: Avoid entering resize-pending state when we don't have a buffer. We'd like bufferless Surfaces to always behave as if it were scaling mode SCALE_TO_WINDOW. Some additional discussion in inline comment. Test: Transaction_test.cpp Change-Id: Ifb176b7b05954c1d3d9ee885cb8f4c51559b922b --- services/surfaceflinger/Layer.cpp | 35 ++++++++++++---------- services/surfaceflinger/tests/Transaction_test.cpp | 35 ++++++++++++++++++++++ 2 files changed, 55 insertions(+), 15 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9435a187d9..9cc1021057 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1687,23 +1687,28 @@ uint32_t Layer::doTransaction(uint32_t flags) { c.requested.w, c.requested.h); } - const bool resizePending = (c.requested.w != c.active.w) || - (c.requested.h != c.active.h); + // Don't let Layer::doTransaction update the drawing state + // if we have a pending resize, unless we are in fixed-size mode. + // the drawing state will be updated only once we receive a buffer + // with the correct size. + // + // In particular, we want to make sure the clip (which is part + // of the geometry state) is latched together with the size but is + // latched immediately when no resizing is involved. + // + // If a sideband stream is attached, however, we want to skip this + // optimization so that transactions aren't missed when a buffer + // never arrives + // + // In the case that we don't have a buffer we ignore other factors + // and avoid entering the resizePending state. At a high level the + // resizePending state is to avoid applying the state of the new buffer + // to the old buffer. However in the state where we don't have an old buffer + // there is no such concern but we may still be being used as a parent layer. + const bool resizePending = ((c.requested.w != c.active.w) || + (c.requested.h != c.active.h)) && (mActiveBuffer != nullptr); if (!isFixedSize()) { if (resizePending && mSidebandStream == NULL) { - // don't let Layer::doTransaction update the drawing state - // if we have a pending resize, unless we are in fixed-size mode. - // the drawing state will be updated only once we receive a buffer - // with the correct size. - // - // in particular, we want to make sure the clip (which is part - // of the geometry state) is latched together with the size but is - // latched immediately when no resizing is involved. - // - // If a sideband stream is attached, however, we want to skip this - // optimization so that transactions aren't missed when a buffer - // never arrives - flags |= eDontUpdateGeometryState; } } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index dea6503e4e..76935ff168 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -788,6 +788,41 @@ TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) { } } +TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { + sp sc; + + sp childNoBuffer = + mComposerClient->createSurface(String8("Bufferless child"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + sp childBuffer = mComposerClient->createSurface( + String8("Buffered child"), 20, 20, + PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get()); + fillSurfaceRGBA8(childBuffer, 200, 200, 200); + + SurfaceComposerClient::openGlobalTransaction(); + childNoBuffer->show(); + childBuffer->show(); + SurfaceComposerClient::closeGlobalTransaction(); + + + { + ScreenCapture::captureScreen(&sc); + sc->expectChildColor(73, 73); + sc->expectFGColor(74, 74); + } + + SurfaceComposerClient::openGlobalTransaction(); + childNoBuffer->setSize(20, 20); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&sc); + sc->expectChildColor(73, 73); + sc->expectChildColor(74, 74); + } +} + class ChildLayerTest : public LayerUpdateTest { protected: void SetUp() override { -- 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/Layer.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 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/Layer.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 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/Layer.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 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/Layer.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 b1154d14ac8055f77e861c7ec8ef9c9f63c3a899 Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 31 Oct 2017 14:15:36 -0700 Subject: Compute crop using all ancestors, not just immediate parent The current computeCrop function only handles intersecting with the parent's crop and not traversing to the top most parent. This change will recurse and intersect all the ancestor's crop with the current layer's crop. Test: Created a parent layer several layer's above the current layer that had a crop. Before, the content would stretch. With the change, the content is the correct size. Change-Id: I592e0afdfc9db574c5ccc79aacedfbd42357c8f7 --- services/surfaceflinger/Layer.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 27739ce074..dbace322b6 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -546,6 +546,13 @@ Rect Layer::computeInitialCrop(const sp& hw) const { activeCrop.clear(); } } + + const auto& p = mDrawingParent.promote(); + if (p != nullptr) { + auto parentCrop = p->computeInitialCrop(hw); + activeCrop.intersect(parentCrop, &activeCrop); + } + return activeCrop; } @@ -559,11 +566,6 @@ FloatRect Layer::computeCrop(const sp& hw) const { // Screen space to make reduction to parent crop clearer. Rect activeCrop = computeInitialCrop(hw); - const auto& p = mDrawingParent.promote(); - if (p != nullptr) { - auto parentCrop = p->computeInitialCrop(hw); - activeCrop.intersect(parentCrop, &activeCrop); - } Transform t = getTransform(); // Back to layer space to work with the content crop. activeCrop = t.inverse().transform(activeCrop); -- cgit v1.2.3-59-g8ed1b From 80de6f350cb23e8a78ad05ae4f8b781ff6fc681a Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Mon, 30 Oct 2017 11:24:08 -0700 Subject: Fix surfaceflinger on integer sanitized builds. Refactors unsigned integer overflows in do_compare to fix integer overflow sanitized builds. Also disables sanitization in Layer::makeTraversalList. Test: Compiled and checked output from sanitizer. Bug: 30969751 Change-Id: I1a6d73435495e8b3ba3edb2587f62e4a0f2662f3 --- services/surfaceflinger/Layer.cpp | 3 ++- services/surfaceflinger/LayerVector.cpp | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 56328c9b3d..aa7635d82f 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -71,7 +71,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, : contentDirty(false), sequence(uint32_t(android_atomic_inc(&sSequence))), mFlinger(flinger), - mTextureName(-1U), + mTextureName(UINT32_MAX), mPremultipliedAlpha(true), mName("unnamed"), mFormat(PIXEL_FORMAT_NONE), @@ -2700,6 +2700,7 @@ int32_t Layer::getZ() const { return mDrawingState.z; } +__attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList(LayerVector::StateSet stateSet) { LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid, "makeTraversalList received invalid stateSet"); diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp index 2233e78c2b..d0f8fbea22 100644 --- a/services/surfaceflinger/LayerVector.cpp +++ b/services/surfaceflinger/LayerVector.cpp @@ -35,14 +35,17 @@ int LayerVector::do_compare(const void* lhs, const void* rhs) const uint32_t ls = l->getCurrentState().layerStack; uint32_t rs = r->getCurrentState().layerStack; if (ls != rs) - return ls - rs; + return (ls > rs) ? 1 : -1; uint32_t lz = l->getCurrentState().z; uint32_t rz = r->getCurrentState().z; if (lz != rz) - return lz - rz; + return (lz > rz) ? 1 : -1; - return l->sequence - r->sequence; + if (l->sequence == r->sequence) + return 0; + + return (l->sequence > r->sequence) ? 1 : -1; } void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) const { -- cgit v1.2.3-59-g8ed1b From 9ab4bd13bcd32cbe2f334cccce0a4d8cb22e14e7 Mon Sep 17 00:00:00 2001 From: chaviw Date: Fri, 3 Nov 2017 13:11:00 -0700 Subject: Remove layer from previous relative list. If a layer is getting a new zOrderRelative, it needs to remove itself from its previous zOrderRelative's list, if it had one. Test: Open app that opens the ime. Switch to another app that opens the ime. Relative layers are updated properly. Change-Id: I54fbfc0f926d39a1630f3b2faed04fbf428b4fe3 --- services/surfaceflinger/Layer.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5405971afa..0525607c35 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1868,6 +1868,10 @@ bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t z) { mCurrentState.modified = true; mCurrentState.z = z; + auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote(); + if (oldZOrderRelativeOf != nullptr) { + oldZOrderRelativeOf->removeZOrderRelative(this); + } mCurrentState.zOrderRelativeOf = relative; relative->addZOrderRelative(this); -- 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/Layer.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 41fdfc920e2a479add53a1936c3ae76cdbea41db Mon Sep 17 00:00:00 2001 From: David Sodman Date: Mon, 6 Nov 2017 16:09:56 -0800 Subject: Run clang-format on Layer/SurfaceFlinger files Run clang-format on changes introduced by the Layer refactor Test: Compile/Manual run Change-Id: I3042cb265d2a00c694f0d6d29cce878dbb069f50 --- services/surfaceflinger/BufferLayer.cpp | 18 +- services/surfaceflinger/BufferLayer.h | 8 +- services/surfaceflinger/ColorLayer.cpp | 14 +- services/surfaceflinger/ColorLayer.h | 8 +- services/surfaceflinger/Layer.cpp | 434 +++++++++++++------------------- services/surfaceflinger/Layer.h | 125 ++++----- 6 files changed, 252 insertions(+), 355 deletions(-) mode change 100755 => 100644 services/surfaceflinger/Layer.cpp (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index ccb65f6df2..8f5dea2691 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -99,11 +99,9 @@ BufferLayer::~BufferLayer() { #endif } -bool BufferLayer::isProtected() const -{ +bool BufferLayer::isProtected() const { const sp& activeBuffer(mActiveBuffer); - return (activeBuffer != 0) && - (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); + return (activeBuffer != 0) && (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); } bool BufferLayer::isVisible() const { @@ -140,9 +138,9 @@ status_t BufferLayer::setBuffers(uint32_t w, uint32_t h, PixelFormat format, uin } 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); + 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) { @@ -605,8 +603,7 @@ void BufferLayer::setPerFrameData(const sp& hw, } #endif -bool BufferLayer::isOpaque(const Layer::State& s) const -{ +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)) { @@ -730,8 +727,7 @@ bool BufferLayer::getOpacityForFormat(uint32_t format) { return true; } -void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, - bool useIdentityTransform) const { +void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { const State& s(getDrawingState()); computeGeometry(renderArea, mMesh, useIdentityTransform); diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index b245f2976e..882649ba70 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -16,8 +16,8 @@ #pragma once -#include "Layer.h" #include "Client.h" +#include "Layer.h" #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposerBufferCache.h" #include "FrameTracker.h" @@ -118,7 +118,8 @@ public: #ifdef USE_HWC2 void setPerFrameData(const sp& displayDevice); #else - void setPerFrameData(const sp& hw, HWComposer::HWCLayerInterface& layer); + void setPerFrameData(const sp& hw, + HWComposer::HWCLayerInterface& layer); #endif bool isOpaque(const Layer::State& s) const override; @@ -137,8 +138,7 @@ private: static bool getOpacityForFormat(uint32_t format); // drawing - void drawWithOpenGL(const RenderArea& renderArea, - bool useIdentityTransform) const; + void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const; // Temporary - Used only for LEGACY camera mode. uint32_t getProducerStickyTransform() const; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 72fdaaa654..500f81f263 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -18,8 +18,8 @@ #undef LOG_TAG #define LOG_TAG "ColorLayer" -#include #include +#include #include #include @@ -28,17 +28,16 @@ #include #include "ColorLayer.h" -#include "SurfaceFlinger.h" #include "DisplayDevice.h" #include "RenderEngine/RenderEngine.h" +#include "SurfaceFlinger.h" namespace android { // --------------------------------------------------------------------------- -ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags) +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) { - // drawing state & current state are identical mDrawingState = mCurrentState; } @@ -46,12 +45,12 @@ ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp& client, void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, bool useIdentityTransform) const { const State& s(getDrawingState()); - if (s.color.a>0) { + if (s.color.a > 0) { Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); computeGeometry(renderArea, mesh, useIdentityTransform); RenderEngine& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */, - true /* disableTexture */, s.color); + true /* disableTexture */, s.color); engine.drawMesh(mesh); engine.disableBlending(); } @@ -62,7 +61,6 @@ bool ColorLayer::isVisible() const { return !isHiddenByPolicy() && s.color.a; } - // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index c68ad023e1..89013274af 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -28,16 +28,16 @@ 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); + 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 RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const; + bool useIdentityTransform) const; bool isVisible() const override; virtual bool isOpaque(const Layer::State&) const { return false; } - virtual bool isFixedSize() const { return true; } + virtual bool isFixedSize() const { return true; } void notifyAvailableFrames() override {} PixelFormat getPixelFormat() const override { return PIXEL_FORMAT_NONE; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp old mode 100755 new mode 100644 index 763488c8f5..a318a8f46a --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -19,10 +19,10 @@ #define LOG_TAG "Layer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include +#include #include +#include #include -#include #include #include @@ -43,13 +43,13 @@ #include #include -#include "clz.h" #include "Colorizer.h" #include "DisplayDevice.h" #include "Layer.h" #include "LayerRejecter.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" +#include "clz.h" #include "DisplayHardware/HWComposer.h" @@ -58,14 +58,14 @@ #include #include "LayerProtoHelper.h" -#define DEBUG_RESIZE 0 +#define DEBUG_RESIZE 0 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) +Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, + uint32_t h, uint32_t flags) : contentDirty(false), sequence(uint32_t(android_atomic_inc(&sSequence))), mFlinger(flinger), @@ -97,18 +97,14 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, mQueueItems(), mLastFrameNumberReceived(0), mAutoRefresh(false), - mFreezeGeometryUpdates(false) -{ + mFreezeGeometryUpdates(false) { mCurrentCrop.makeInvalid(); uint32_t layerFlags = 0; - if (flags & ISurfaceComposerClient::eHidden) - layerFlags |= layer_state_t::eLayerHidden; - if (flags & ISurfaceComposerClient::eOpaque) - layerFlags |= layer_state_t::eLayerOpaque; - if (flags & ISurfaceComposerClient::eSecure) - layerFlags |= layer_state_t::eLayerSecure; + if (flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden; + if (flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque; + if (flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure; mName = name; mTransactionName = String8("TX - ") + mName; @@ -138,8 +134,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY); nsecs_t displayPeriod = activeConfig->getVsyncPeriod(); #else - nsecs_t displayPeriod = - flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); + nsecs_t displayPeriod = flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); #endif mFrameTracker.setDisplayRefreshPeriod(displayPeriod); @@ -148,8 +143,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, mFrameEventHistory.initializeCompositorTiming(compositorTiming); } -void Layer::onFirstRef() { -} +void Layer::onFirstRef() {} Layer::~Layer() { mFrameTracker.logAndResetStats(mName); @@ -170,7 +164,7 @@ void Layer::onLayerDisplayed(const sp& releaseFence) { } #else void Layer::onLayerDisplayed(const sp& /* hw */, - HWComposer::HWCLayerInterface* layer) { + HWComposer::HWCLayerInterface* layer) { if (layer) { layer->onDisplayed(); mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence()); @@ -233,8 +227,7 @@ sp Layer::getHandle() { #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); + 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; @@ -243,7 +236,7 @@ bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) { hwcInfo.hwc = hwc; hwcInfo.layer = layer; layer->setLayerDestroyedListener( - [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);}); + [this, hwcId](HWC2::Layer* /*layer*/) { mHwcLayers.erase(hwcId); }); return true; } @@ -252,14 +245,12 @@ void Layer::destroyHwcLayer(int32_t hwcId) { return; } auto& hwcInfo = mHwcLayers[hwcId]; - LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, - "Attempt to destroy null layer"); + 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"); + LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, "Stale layer entry in mHwcLayers"); } void Layer::destroyAllHwcLayers() { @@ -269,7 +260,7 @@ void Layer::destroyAllHwcLayers() { destroyHwcLayer(mHwcLayers.begin()->first); } LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(), - "All hardware composer layers should have been destroyed"); + "All hardware composer layers should have been destroyed"); } #endif @@ -393,7 +384,7 @@ Rect Layer::computeInitialCrop(const sp& hw) const { activeCrop.clear(); } if (!s.finalCrop.isEmpty()) { - if(!activeCrop.intersect(s.finalCrop, &activeCrop)) { + if (!activeCrop.intersect(s.finalCrop, &activeCrop)) { activeCrop.clear(); } } @@ -443,16 +434,13 @@ FloatRect Layer::computeCrop(const sp& hw) const { * the code below applies the primary display's inverse transform to the * buffer */ - uint32_t invTransformOrient = - DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransformOrient = DisplayDevice::getPrimaryDisplayOrientationTransform(); // calculate the inverse transform if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) { - invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | - NATIVE_WINDOW_TRANSFORM_FLIP_H; + invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } // and apply to the current transform - invTransform = (Transform(invTransformOrient) * Transform(invTransform)) - .getOrientation(); + invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation(); } int winWidth = s.active.w; @@ -466,27 +454,25 @@ FloatRect Layer::computeCrop(const sp& hw) const { bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0; bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0; if (is_h_flipped == is_v_flipped) { - invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | - NATIVE_WINDOW_TRANSFORM_FLIP_H; + invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } winWidth = s.active.h; winHeight = s.active.w; } - const Rect winCrop = activeCrop.transform( - invTransform, s.active.w, s.active.h); + const Rect winCrop = activeCrop.transform(invTransform, s.active.w, s.active.h); // below, crop is intersected with winCrop expressed in crop's coordinate space - float xScale = crop.getWidth() / float(winWidth); + float xScale = crop.getWidth() / float(winWidth); float yScale = crop.getHeight() / float(winHeight); - float insetL = winCrop.left * xScale; - float insetT = winCrop.top * yScale; - float insetR = (winWidth - winCrop.right ) * xScale; + float insetL = winCrop.left * xScale; + float insetT = winCrop.top * yScale; + float insetR = (winWidth - winCrop.right) * xScale; float insetB = (winHeight - winCrop.bottom) * yScale; - crop.left += insetL; - crop.top += insetT; - crop.right -= insetR; + crop.left += insetL; + crop.top += insetT; + crop.right -= insetR; crop.bottom -= insetB; return crop; @@ -495,9 +481,7 @@ FloatRect Layer::computeCrop(const sp& hw) const { #ifdef USE_HWC2 void Layer::setGeometry(const sp& displayDevice, uint32_t z) #else -void Layer::setGeometry( - const sp& hw, - HWComposer::HWCLayerInterface& layer) +void Layer::setGeometry(const sp& hw, HWComposer::HWCLayerInterface& layer) #endif { #ifdef USE_HWC2 @@ -529,18 +513,18 @@ void Layer::setGeometry( #ifdef USE_HWC2 auto blendMode = HWC2::BlendMode::None; if (!isOpaque(s) || getAlpha() != 1.0f) { - blendMode = mPremultipliedAlpha ? - HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage; + blendMode = + mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage; } auto error = hwcLayer->setBlendMode(blendMode); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set blend mode %s:" - " %s (%d)", mName.string(), to_string(blendMode).c_str(), - to_string(error).c_str(), static_cast(error)); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set blend mode %s:" + " %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); + layer.setBlending(mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE); } #endif @@ -552,9 +536,9 @@ void Layer::setGeometry( Rect activeCrop(s.crop); activeCrop = t.transform(activeCrop); #ifdef USE_HWC2 - if(!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) { + if (!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) { #else - if(!activeCrop.intersect(hw->getViewport(), &activeCrop)) { + if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) { #endif activeCrop.clear(); } @@ -565,22 +549,20 @@ void Layer::setGeometry( // transform.inverse().transform(transform.transform(Rect)) != Rect // in which case we need to make sure the final rect is clipped to the // display bounds. - if(!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) { + if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) { activeCrop.clear(); } // mark regions outside the crop as transparent activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top)); - activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, - s.active.w, s.active.h)); - activeTransparentRegion.orSelf(Rect(0, activeCrop.top, - activeCrop.left, activeCrop.bottom)); - activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top, - s.active.w, activeCrop.bottom)); + activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, s.active.w, s.active.h)); + activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom)); + activeTransparentRegion.orSelf( + Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom)); } Rect frame(t.transform(computeBounds(activeTransparentRegion))); if (!s.finalCrop.isEmpty()) { - if(!frame.intersect(s.finalCrop, &frame)) { + if (!frame.intersect(s.finalCrop, &frame)) { frame.clear(); } } @@ -592,10 +574,9 @@ void Layer::setGeometry( Rect transformedFrame = tr.transform(frame); error = hwcLayer->setDisplayFrame(transformedFrame); if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)", - mName.string(), transformedFrame.left, transformedFrame.top, - transformedFrame.right, transformedFrame.bottom, - to_string(error).c_str(), static_cast(error)); + ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)", mName.string(), + transformedFrame.left, transformedFrame.top, transformedFrame.right, + transformedFrame.bottom, to_string(error).c_str(), static_cast(error)); } else { hwcInfo.displayFrame = transformedFrame; } @@ -604,23 +585,23 @@ void Layer::setGeometry( error = hwcLayer->setSourceCrop(sourceCrop); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: " - "%s (%d)", mName.string(), sourceCrop.left, sourceCrop.top, - sourceCrop.right, sourceCrop.bottom, to_string(error).c_str(), - static_cast(error)); + "%s (%d)", + mName.string(), sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom, + to_string(error).c_str(), static_cast(error)); } else { hwcInfo.sourceCrop = sourceCrop; } 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(), - static_cast(error)); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set plane alpha %.3f: " + "%s (%d)", + mName.string(), alpha, to_string(error).c_str(), static_cast(error)); error = hwcLayer->setZOrder(z); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", - mName.string(), z, to_string(error).c_str(), - static_cast(error)); + ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", mName.string(), z, + to_string(error).c_str(), static_cast(error)); int type = s.type; int appId = s.appId; @@ -632,8 +613,8 @@ void Layer::setGeometry( } error = hwcLayer->setInfo(type, appId); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", - mName.string(), static_cast(error)); + 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(); @@ -641,7 +622,7 @@ void Layer::setGeometry( const Transform& tr(hw->getTransform()); layer.setFrame(tr.transform(frame)); layer.setCrop(computeCrop(hw)); - layer.setPlaneAlpha(static_cast(std::round(255.0f*getAlpha()))); + layer.setPlaneAlpha(static_cast(std::round(255.0f * getAlpha()))); #endif /* @@ -660,12 +641,10 @@ void Layer::setGeometry( * the code below applies the primary display's inverse transform to the * buffer */ - uint32_t invTransform = - DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); // calculate the inverse transform if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { - invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | - NATIVE_WINDOW_TRANSFORM_FLIP_H; + invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } /* @@ -686,9 +665,11 @@ void Layer::setGeometry( } else { auto transform = static_cast(orientation); auto error = hwcLayer->setTransform(transform); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set transform %s: " - "%s (%d)", mName.string(), to_string(transform).c_str(), - to_string(error).c_str(), static_cast(error)); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set transform %s: " + "%s (%d)", + mName.string(), to_string(transform).c_str(), to_string(error).c_str(), + static_cast(error)); } #else if (orientation & Transform::ROT_INVALID) { @@ -722,14 +703,14 @@ void Layer::setPerFrameData(const sp& displayDevice) { 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)); + 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)); + to_string(error).c_str(), static_cast(error)); surfaceDamageRegion.dump(LOG_TAG); } @@ -739,16 +720,15 @@ void Layer::setPerFrameData(const sp& displayDevice) { 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)); + 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)) { + (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) { ALOGV("[%s] Requesting Client composition", mName.string()); setCompositionType(hwcId, HWC2::Composition::Client); return; @@ -759,13 +739,12 @@ void Layer::setPerFrameData(const sp& displayDevice) { setCompositionType(hwcId, HWC2::Composition::SolidColor); 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}); + 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)); + 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 @@ -773,7 +752,7 @@ void Layer::setPerFrameData(const sp& displayDevice) { 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)); + to_string(error).c_str(), static_cast(error)); } return; @@ -791,28 +770,25 @@ void Layer::setPerFrameData(const sp& displayDevice) { 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)); + 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); + 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)); + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), mActiveBuffer->handle, + to_string(error).c_str(), static_cast(error)); } } #else void Layer::setPerFrameData(const sp& hw, - HWComposer::HWCLayerInterface& layer) { + 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. @@ -837,8 +813,7 @@ void Layer::setPerFrameData(const sp& hw, #ifdef USE_HWC2 void Layer::updateCursorPosition(const sp& displayDevice) { auto hwcId = displayDevice->getHwcDisplayId(); - if (mHwcLayers.count(hwcId) == 0 || - getCompositionType(hwcId) != HWC2::Composition::Cursor) { + if (mHwcLayers.count(hwcId) == 0 || getCompositionType(hwcId) != HWC2::Composition::Cursor) { return; } @@ -861,22 +836,23 @@ void Layer::updateCursorPosition(const sp& displayDevice) { auto& displayTransform(displayDevice->getTransform()); auto position = displayTransform.transform(frame); - auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left, - position.top); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " - "to (%d, %d): %s (%d)", mName.string(), position.left, - position.top, to_string(error).c_str(), - static_cast(error)); + auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left, position.top); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set cursor position " + "to (%d, %d): %s (%d)", + mName.string(), position.left, position.top, to_string(error).c_str(), + static_cast(error)); } #else void Layer::setAcquireFence(const sp& /* hw */, - HWComposer::HWCLayerInterface& layer) { + 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) { + if (layer.getCompositionType() == HWC_OVERLAY || + layer.getCompositionType() == HWC_CURSOR_OVERLAY) { sp fence = mSurfaceFlingerConsumer->getCurrentFence(); if (fence->isValid()) { fenceFd = fence->dup(); @@ -888,9 +864,7 @@ void Layer::setAcquireFence(const sp& /* hw */, layer.setAcquireFenceFd(fenceFd); } -Rect Layer::getPosition( - const sp& hw) -{ +Rect Layer::getPosition(const sp& hw) { // this gives us only the "orientation" component of the transform const State& s(getCurrentState()); @@ -928,10 +902,8 @@ void Layer::draw(const RenderArea& renderArea) const { onDraw(renderArea, Region(renderArea.getBounds()), false); } -void Layer::clearWithOpenGL(const RenderArea& renderArea, - float red, float green, float blue, - float alpha) const -{ +void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue, + float alpha) const { RenderEngine& engine(mFlinger->getRenderEngine()); computeGeometry(renderArea, mMesh, false); engine.setupFillWithColor(red, green, blue, alpha); @@ -939,29 +911,29 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea, } void Layer::clearWithOpenGL(const RenderArea& renderArea) const { - clearWithOpenGL(renderArea, 0,0,0,0); + clearWithOpenGL(renderArea, 0, 0, 0, 0); } #ifdef USE_HWC2 -void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, - bool callIntoHwc) { +void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) { if (mHwcLayers.count(hwcId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); return; } auto& hwcInfo = mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; - ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), - to_string(type).c_str(), static_cast(callIntoHwc)); + ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(), + static_cast(callIntoHwc)); if (hwcInfo.compositionType != type) { ALOGV(" actually setting"); hwcInfo.compositionType = type; if (callIntoHwc) { auto error = hwcLayer->setCompositionType(type); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set " - "composition type %s: %s (%d)", mName.string(), - to_string(type).c_str(), to_string(error).c_str(), - static_cast(error)); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set " + "composition type %s: %s (%d)", + mName.string(), to_string(type).c_str(), to_string(error).c_str(), + static_cast(error)); } } } @@ -1067,13 +1039,12 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, position[1] = renderAreaTransform.transform(lb); position[2] = renderAreaTransform.transform(rb); position[3] = renderAreaTransform.transform(rt); - for (size_t i=0 ; i<4 ; i++) { + for (size_t i = 0; i < 4; i++) { position[i].y = height - position[i].y; } } -bool Layer::isSecure() const -{ +bool Layer::isSecure() const { const Layer::State& s(mDrawingState); return (s.flags & layer_state_t::eLayerSecure); } @@ -1088,8 +1059,7 @@ void Layer::setCoveredRegion(const Region& coveredRegion) { this->coveredRegion = coveredRegion; } -void Layer::setVisibleNonTransparentRegion(const Region& - setVisibleNonTransparentRegion) { +void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparentRegion) { // always called from main thread this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; } @@ -1114,8 +1084,7 @@ void Layer::pushPendingState() { // to be applied as per normal (no synchronization). mCurrentState.barrierLayer = nullptr; } else { - auto syncPoint = std::make_shared( - mCurrentState.frameNumber); + auto syncPoint = std::make_shared(mCurrentState.frameNumber); if (barrierLayer->addSyncPoint(syncPoint)) { mRemoteSyncPoints.push_back(std::move(syncPoint)); } else { @@ -1136,8 +1105,8 @@ void Layer::pushPendingState() { void Layer::popPendingState(State* stateToCommit) { auto oldFlags = stateToCommit->flags; *stateToCommit = mPendingStates[0]; - stateToCommit->flags = (oldFlags & ~stateToCommit->mask) | - (stateToCommit->flags & stateToCommit->mask); + stateToCommit->flags = + (oldFlags & ~stateToCommit->mask) | (stateToCommit->flags & stateToCommit->mask); mPendingStates.removeAt(0); ATRACE_INT(mTransactionName.string(), mPendingStates.size()); @@ -1157,10 +1126,8 @@ bool Layer::applyPendingStates(State* stateToCommit) { continue; } - if (mRemoteSyncPoints.front()->getFrameNumber() != - mPendingStates[0].frameNumber) { - ALOGE("[%s] Unexpected sync point frame number found", - mName.string()); + if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber) { + ALOGE("[%s] Unexpected sync point frame number found", mName.string()); // Signal our end of the sync point and then dispose of it mRemoteSyncPoints.front()->setTransactionApplied(); @@ -1207,40 +1174,25 @@ uint32_t Layer::doTransaction(uint32_t flags) { const Layer::State& s(getDrawingState()); - const bool sizeChanged = (c.requested.w != s.requested.w) || - (c.requested.h != s.requested.h); + const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h); 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" - " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" - " requested={ wh={%4u,%4u} }}\n" - " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" - " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), mCurrentTransform, - getEffectiveScalingMode(), - c.active.w, c.active.h, - c.crop.left, - c.crop.top, - c.crop.right, - c.crop.bottom, - c.crop.getWidth(), - c.crop.getHeight(), - c.requested.w, c.requested.h, - s.active.w, s.active.h, - s.crop.left, - s.crop.top, - s.crop.right, - s.crop.bottom, - s.crop.getWidth(), - s.crop.getHeight(), - s.requested.w, s.requested.h); + "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n" + " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" + " requested={ wh={%4u,%4u} }}\n" + " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" + " requested={ wh={%4u,%4u} }}\n", + this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), c.active.w, + c.active.h, c.crop.left, c.crop.top, c.crop.right, c.crop.bottom, + c.crop.getWidth(), c.crop.getHeight(), c.requested.w, c.requested.h, s.active.w, + s.active.h, s.crop.left, s.crop.top, s.crop.right, s.crop.bottom, + s.crop.getWidth(), s.crop.getHeight(), s.requested.w, s.requested.h); // record the new size, form this point on, when the client request // a buffer, it'll get the new size. - mSurfaceFlingerConsumer->setDefaultBufferSize( - c.requested.w, c.requested.h); + mSurfaceFlingerConsumer->setDefaultBufferSize(c.requested.w, c.requested.h); } // Don't let Layer::doTransaction update the drawing state @@ -1261,8 +1213,8 @@ uint32_t Layer::doTransaction(uint32_t flags) { // resizePending state is to avoid applying the state of the new buffer // to the old buffer. However in the state where we don't have an old buffer // there is no such concern but we may still be being used as a parent layer. - const bool resizePending = ((c.requested.w != c.active.w) || - (c.requested.h != c.active.h)) && (mActiveBuffer != nullptr); + const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) && + (mActiveBuffer != nullptr); if (!isFixedSize()) { if (resizePending && mSidebandStream == NULL) { flags |= eDontUpdateGeometryState; @@ -1311,8 +1263,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { // we may use linear filtering, if the matrix scales us const uint8_t type = c.active.transform.getType(); - mNeedsFiltering = (!c.active.transform.preserveRects() || - (type >= Transform::SCALE)); + mNeedsFiltering = (!c.active.transform.preserveRects() || (type >= Transform::SCALE)); } // If the layer is hidden, signal and clear out all local sync points so @@ -1375,8 +1326,7 @@ bool Layer::setChildLayer(const sp& childLayer, int32_t z) { } bool Layer::setLayer(int32_t z) { - if (mCurrentState.z == z) - return false; + if (mCurrentState.z == z) return false; mCurrentState.sequence++; mCurrentState.z = z; mCurrentState.modified = true; @@ -1434,8 +1384,7 @@ bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t z) { } bool Layer::setSize(uint32_t w, uint32_t h) { - if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) - return false; + if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false; mCurrentState.requested.w = w; mCurrentState.requested.h = h; mCurrentState.modified = true; @@ -1443,8 +1392,7 @@ bool Layer::setSize(uint32_t w, uint32_t h) { return true; } bool Layer::setAlpha(float alpha) { - if (mCurrentState.color.a == alpha) - return false; + if (mCurrentState.color.a == alpha) return false; mCurrentState.sequence++; mCurrentState.color.a = alpha; mCurrentState.modified = true; @@ -1453,8 +1401,8 @@ bool Layer::setAlpha(float alpha) { } bool Layer::setColor(const half3& color) { - if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g - && color.b == mCurrentState.color.b) + if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g && + color.b == mCurrentState.color.b) return false; mCurrentState.sequence++; @@ -1468,8 +1416,7 @@ bool Layer::setColor(const half3& color) { bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) { mCurrentState.sequence++; - mCurrentState.requested.transform.set( - matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -1482,8 +1429,7 @@ bool Layer::setTransparentRegionHint(const Region& transparent) { } bool Layer::setFlags(uint8_t flags, uint8_t mask) { const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); - if (mCurrentState.flags == newFlags) - return false; + if (mCurrentState.flags == newFlags) return false; mCurrentState.sequence++; mCurrentState.flags = newFlags; mCurrentState.mask = mask; @@ -1493,8 +1439,7 @@ bool Layer::setFlags(uint8_t flags, uint8_t mask) { } bool Layer::setCrop(const Rect& crop, bool immediate) { - if (mCurrentState.requestedCrop == crop) - return false; + if (mCurrentState.requestedCrop == crop) return false; mCurrentState.sequence++; mCurrentState.requestedCrop = crop; if (immediate && !mFreezeGeometryUpdates) { @@ -1508,8 +1453,7 @@ bool Layer::setCrop(const Rect& crop, bool immediate) { } bool Layer::setFinalCrop(const Rect& crop, bool immediate) { - if (mCurrentState.requestedFinalCrop == crop) - return false; + if (mCurrentState.requestedFinalCrop == crop) return false; mCurrentState.sequence++; mCurrentState.requestedFinalCrop = crop; if (immediate && !mFreezeGeometryUpdates) { @@ -1523,23 +1467,21 @@ bool Layer::setFinalCrop(const Rect& crop, bool immediate) { } bool Layer::setOverrideScalingMode(int32_t scalingMode) { - if (scalingMode == mOverrideScalingMode) - return false; + if (scalingMode == mOverrideScalingMode) return false; mOverrideScalingMode = scalingMode; setTransactionFlags(eTransactionNeeded); return true; } void Layer::setInfo(uint32_t type, uint32_t appId) { - mCurrentState.appId = appId; - mCurrentState.type = type; - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); + mCurrentState.appId = appId; + mCurrentState.type = type; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); } bool Layer::setLayerStack(uint32_t layerStack) { - if (mCurrentState.layerStack == layerStack) - return false; + if (mCurrentState.layerStack == layerStack) return false; mCurrentState.sequence++; mCurrentState.layerStack = layerStack; mCurrentState.modified = true; @@ -1548,8 +1490,7 @@ bool Layer::setLayerStack(uint32_t layerStack) { } bool Layer::setDataSpace(android_dataspace dataSpace) { - if (mCurrentState.dataSpace == dataSpace) - return false; + if (mCurrentState.dataSpace == dataSpace) return false; mCurrentState.sequence++; mCurrentState.dataSpace = dataSpace; mCurrentState.modified = true; @@ -1569,8 +1510,7 @@ uint32_t Layer::getLayerStack() const { return p->getLayerStack(); } -void Layer::deferTransactionUntil(const sp& barrierLayer, - uint64_t frameNumber) { +void Layer::deferTransactionUntil(const sp& barrierLayer, uint64_t frameNumber) { mCurrentState.barrierLayer = barrierLayer; mCurrentState.frameNumber = frameNumber; // We don't set eTransactionNeeded, because just receiving a deferral @@ -1582,8 +1522,7 @@ void Layer::deferTransactionUntil(const sp& barrierLayer, mCurrentState.modified = false; } -void Layer::deferTransactionUntil(const sp& barrierHandle, - uint64_t frameNumber) { +void Layer::deferTransactionUntil(const sp& barrierHandle, uint64_t frameNumber) { sp handle = static_cast(barrierHandle.get()); deferTransactionUntil(handle->owner.promote(), frameNumber); } @@ -1614,40 +1553,38 @@ bool Layer::shouldPresentNow(const DispSync& dispSync) const { return false; } auto timestamp = mQueueItems[0].mTimestamp; - nsecs_t expectedPresent = - mSurfaceFlingerConsumer->computeExpectedPresent(dispSync); + nsecs_t expectedPresent = mSurfaceFlingerConsumer->computeExpectedPresent(dispSync); // Ignore timestamps more than a second in the future bool isPlausible = timestamp < (expectedPresent + s2ns(1)); - ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible " - "relative to expectedPresent %" PRId64, mName.string(), timestamp, - expectedPresent); + ALOGW_IF(!isPlausible, + "[%s] Timestamp %" PRId64 " seems implausible " + "relative to expectedPresent %" PRId64, + mName.string(), timestamp, expectedPresent); bool isDue = timestamp < expectedPresent; return isDue || !isPlausible; } bool Layer::onPostComposition(const std::shared_ptr& glDoneFence, - const std::shared_ptr& presentFence, - const CompositorTiming& compositorTiming) { + const std::shared_ptr& presentFence, + const CompositorTiming& compositorTiming) { // mFrameLatencyNeeded is true when a new frame was latched for the // composition. - if (!mFrameLatencyNeeded) - return false; + if (!mFrameLatencyNeeded) return false; // Update mFrameEventHistory. { Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPostComposition(mCurrentFrameNumber, - glDoneFence, presentFence, compositorTiming); + mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, presentFence, + compositorTiming); } // Update mFrameTracker. nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp(); mFrameTracker.setDesiredPresentTime(desiredPresentTime); - std::shared_ptr frameReadyFence = - mSurfaceFlingerConsumer->getCurrentFenceTime(); + std::shared_ptr frameReadyFence = mSurfaceFlingerConsumer->getCurrentFenceTime(); if (frameReadyFence->isValid()) { mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); } else { @@ -1657,14 +1594,12 @@ bool Layer::onPostComposition(const std::shared_ptr& glDoneFence, } if (presentFence->isValid()) { - mFrameTracker.setActualPresentFence( - std::shared_ptr(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)); + mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY)); } mFrameTracker.advanceFrame(); @@ -1681,8 +1616,7 @@ bool Layer::isHiddenByPolicy() const { return s.flags & layer_state_t::eLayerHidden; } -uint32_t Layer::getEffectiveUsage(uint32_t usage) const -{ +uint32_t Layer::getEffectiveUsage(uint32_t usage) const { // TODO: should we do something special if mSecure is set? if (mProtectedByApp) { // need a hardware-protected path to external video sink @@ -1796,14 +1730,11 @@ void Layer::miniDump(String8& result, int32_t hwcId) const { const Layer::State& layerState(getDrawingState()); const HWCInfo& hwcInfo = mHwcLayers.at(hwcId); result.appendFormat(" %10d | ", layerState.z); - result.appendFormat("%10s | ", - to_string(getCompositionType(hwcId)).c_str()); + 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); + result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); const FloatRect& crop = hwcInfo.sourceCrop; - result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, - crop.right, crop.bottom); + result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom); result.append("- - - - - - - - - - - - - - - - - - - - "); result.append("- - - - - - - - - - - - - - - - - - - -\n"); @@ -1827,8 +1758,7 @@ void Layer::getFrameStats(FrameStats* outStats) const { } void Layer::dumpFrameEvents(String8& result) { - result.appendFormat("- Layer %s (%s, %p)\n", - getName().string(), getTypeId(), this); + result.appendFormat("- Layer %s (%s, %p)\n", getName().string(), getTypeId(), this); Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.checkFencesForCompletion(); mFrameEventHistory.dump(result); @@ -1840,7 +1770,7 @@ void Layer::onDisconnect() { } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, - FrameEventHistoryDelta *outDelta) { + FrameEventHistoryDelta* outDelta) { Mutex::Autolock lock(mFrameEventHistoryMutex); if (newTimestamps) { // If there are any unsignaled fences in the aquire timeline at this @@ -1858,18 +1788,14 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, } } -std::vector Layer::getOccupancyHistory( - bool forceFlush) { +std::vector Layer::getOccupancyHistory(bool forceFlush) { std::vector history; - if (!mSurfaceFlingerConsumer) - return {}; + if (!mSurfaceFlingerConsumer) return {}; - status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush, - &history); + status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush, &history); if (result != NO_ERROR) { - ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), - result); + ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result); return {}; } return history; @@ -1990,8 +1916,8 @@ int32_t Layer::getZ() const { return mDrawingState.z; } -__attribute__((no_sanitize("unsigned-integer-overflow"))) -LayerVector Layer::makeTraversalList(LayerVector::StateSet stateSet) { +__attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList( + LayerVector::StateSet stateSet) { LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid, "makeTraversalList received invalid stateSet"); const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; @@ -2046,7 +1972,7 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, LayerVector list = makeTraversalList(stateSet); int32_t i = 0; - for (i = list.size()-1; i>=0; i--) { + for (i = list.size() - 1; i >= 0; i--) { const auto& relative = list[i]; if (relative->getZ() < 0) { break; @@ -2054,7 +1980,7 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, relative->traverseInReverseZOrder(stateSet, visitor); } visitor(this); - for (; i>=0; i--) { + for (; i >= 0; i--) { const auto& relative = list[i]; relative->traverseInReverseZOrder(stateSet, visitor); } @@ -2104,10 +2030,8 @@ Transform Layer::getTransform() const { bufferHeight = p->mActiveBuffer->getWidth(); bufferWidth = p->mActiveBuffer->getHeight(); } - float sx = p->getDrawingState().active.w / - static_cast(bufferWidth); - float sy = p->getDrawingState().active.h / - static_cast(bufferHeight); + float sx = p->getDrawingState().active.w / static_cast(bufferWidth); + float sy = p->getDrawingState().active.h / static_cast(bufferHeight); Transform extraParentScaling; extraParentScaling.set(sx, 0, 0, sy); t = t * extraParentScaling; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ee3bb7ef3f..db94a31c5e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -37,20 +37,20 @@ #include -#include "FrameTracker.h" #include "Client.h" +#include "FrameTracker.h" #include "LayerVector.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" #include "SurfaceFlingerConsumer.h" #include "Transform.h" +#include #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/HWComposerBufferCache.h" +#include "RenderArea.h" #include "RenderEngine/Mesh.h" #include "RenderEngine/Texture.h" -#include -#include "RenderArea.h" #include @@ -69,8 +69,7 @@ class LayerDebugInfo; // --------------------------------------------------------------------------- -class Layer : public virtual RefBase -{ +class Layer : public virtual RefBase { static int32_t sSequence; public: @@ -96,14 +95,11 @@ public: uint32_t h; Transform transform; - inline bool operator ==(const Geometry& rhs) const { - return (w == rhs.w && h == rhs.h) && - (transform.tx() == rhs.transform.tx()) && + inline bool operator==(const Geometry& rhs) const { + return (w == rhs.w && h == rhs.h) && (transform.tx() == rhs.transform.tx()) && (transform.ty() == rhs.transform.ty()); } - inline bool operator !=(const Geometry& rhs) const { - return !operator ==(rhs); - } + inline bool operator!=(const Geometry& rhs) const { return !operator==(rhs); } }; struct State { @@ -156,8 +152,8 @@ public: half4 color; }; - Layer(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags); + Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, + uint32_t h, uint32_t flags); virtual ~Layer(); void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; } @@ -287,7 +283,8 @@ public: */ virtual bool isFixedSize() const = 0; - void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); + void writeToProto(LayerProto* layerInfo, + LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); protected: /* @@ -310,8 +307,7 @@ public: bool getClearClientTarget(int32_t hwcId) const; void updateCursorPosition(const sp& hw); #else - void setGeometry(const sp& hw, - HWComposer::HWCLayerInterface& layer); + void setGeometry(const sp& hw, HWComposer::HWCLayerInterface& layer); void setPerFrameData(const sp& hw, HWComposer::HWCLayerInterface& layer); void setAcquireFence(const sp& hw, HWComposer::HWCLayerInterface& layer); @@ -324,8 +320,7 @@ public: #ifdef USE_HWC2 void onLayerDisplayed(const sp& releaseFence); #else - void onLayerDisplayed(const sp& hw, - HWComposer::HWCLayerInterface* layer); + void onLayerDisplayed(const sp& hw, HWComposer::HWCLayerInterface* layer); #endif bool shouldPresentNow(const DispSync& dispSync) const; @@ -341,8 +336,8 @@ public: * returns true if the layer latched a new buffer this frame. */ bool onPostComposition(const std::shared_ptr& glDoneFence, - const std::shared_ptr& presentFence, - const CompositorTiming& compositorTiming); + const std::shared_ptr& presentFence, + const CompositorTiming& compositorTiming); #ifdef USE_HWC2 // If a buffer was replaced this frame, release the former buffer @@ -380,8 +375,7 @@ public: * setVisibleNonTransparentRegion - called when the visible and * non-transparent region changes. */ - void setVisibleNonTransparentRegion(const Region& - visibleNonTransparentRegion); + void setVisibleNonTransparentRegion(const Region& visibleNonTransparentRegion); /* * latchBuffer - called each time the screen is redrawn and returns whether @@ -405,7 +399,6 @@ public: */ void onRemoved(); - // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. void updateTransformHint(const sp& hw) const; @@ -419,8 +412,9 @@ public: /* * Returns if a frame is queued. */ - bool hasQueuedFrame() const { return mQueuedFrames > 0 || - mSidebandStreamChanged || mAutoRefresh; } + bool hasQueuedFrame() const { + return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; + } int32_t getQueuedFrameCount() const { return mQueuedFrames; } @@ -431,9 +425,7 @@ public: void destroyHwcLayer(int32_t hwcId); void destroyAllHwcLayers(); - bool hasHwcLayer(int32_t hwcId) { - return mHwcLayers.count(hwcId) > 0; - } + bool hasHwcLayer(int32_t hwcId) { return mHwcLayers.count(hwcId) > 0; } HWC2::Layer* getHwcLayer(int32_t hwcId) { if (mHwcLayers.count(hwcId) == 0) { @@ -452,9 +444,9 @@ public: // only for debugging inline const sp& getActiveBuffer() const { return mActiveBuffer; } - inline const State& getDrawingState() const { return mDrawingState; } - inline const State& getCurrentState() const { return mCurrentState; } - inline State& getCurrentState() { return mCurrentState; } + inline const State& getDrawingState() const { return mDrawingState; } + inline const State& getCurrentState() const { return mCurrentState; } + inline State& getCurrentState() { return mCurrentState; } LayerDebugInfo getLayerDebugInfo() const; @@ -473,7 +465,7 @@ public: void onDisconnect(); void addAndGetFrameTimestamps(const NewFrameEventsEntry* newEntry, - FrameEventHistoryDelta* outDelta); + FrameEventHistoryDelta* outDelta); bool getTransformToDisplayInverse() const; @@ -506,6 +498,7 @@ public: // SurfaceFlinger to complete a transaction. void commitChildList(); int32_t getZ() const; + protected: // constant sp mFlinger; @@ -516,23 +509,20 @@ protected: class LayerCleaner { sp mFlinger; wp mLayer; + protected: ~LayerCleaner() { // destroy client resources mFlinger->onLayerDestroyed(mLayer); } + public: - LayerCleaner(const sp& flinger, - const sp& layer) - : mFlinger(flinger), mLayer(layer) { - } + LayerCleaner(const sp& flinger, const sp& layer) + : mFlinger(flinger), mLayer(layer) {} }; - virtual void onFirstRef(); - - friend class SurfaceInterceptor; void commitTransaction(const State& stateToCommit); @@ -546,8 +536,8 @@ protected: Rect computeInitialCrop(const sp& hw) const; // drawing - void clearWithOpenGL(const RenderArea& renderArea, - float r, float g, float b, float alpha) const; + void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b, + float alpha) const; void setParent(const sp& layer); @@ -556,31 +546,20 @@ protected: void removeZOrderRelative(const wp& relative); protected: - class SyncPoint - { + class SyncPoint { public: - explicit SyncPoint(uint64_t frameNumber) : mFrameNumber(frameNumber), - mFrameIsAvailable(false), mTransactionIsApplied(false) {} + explicit SyncPoint(uint64_t frameNumber) + : mFrameNumber(frameNumber), mFrameIsAvailable(false), mTransactionIsApplied(false) {} - uint64_t getFrameNumber() const { - return mFrameNumber; - } + uint64_t getFrameNumber() const { return mFrameNumber; } - bool frameIsAvailable() const { - return mFrameIsAvailable; - } + bool frameIsAvailable() const { return mFrameIsAvailable; } - void setFrameAvailable() { - mFrameIsAvailable = true; - } + void setFrameAvailable() { mFrameIsAvailable = true; } - bool transactionIsApplied() const { - return mTransactionIsApplied; - } + bool transactionIsApplied() const { return mTransactionIsApplied; } - void setTransactionApplied() { - mTransactionIsApplied = true; - } + void setTransactionApplied() { mTransactionIsApplied = true; } private: const uint64_t mFrameNumber; @@ -611,6 +590,7 @@ protected: // Client) or mOverrideScalingMode mode (originating from // the Surface Controller) if set. virtual uint32_t getEffectiveScalingMode() const = 0; + public: /* * The layer handle is just a BBinder object passed to the client @@ -621,11 +601,11 @@ public: * this layer when the handle is destroyed. */ class Handle : public BBinder, public LayerCleaner { - public: - Handle(const sp& flinger, const sp& layer) - : LayerCleaner(flinger, layer), owner(layer) {} + public: + Handle(const sp& flinger, const sp& layer) + : LayerCleaner(flinger, layer), owner(layer) {} - wp owner; + wp owner; }; sp getHandle(); @@ -633,15 +613,15 @@ public: virtual void notifyAvailableFrames() = 0; virtual PixelFormat getPixelFormat() const = 0; bool getPremultipledAlpha() const; -protected: +protected: // ----------------------------------------------------------------------- // constants sp mSurfaceFlingerConsumer; bool mPremultipliedAlpha; String8 mName; - String8 mTransactionName; // A cached version of "TX - " + mName for systraces + String8 mTransactionName; // A cached version of "TX - " + mName for systraces bool mPrimaryDisplayOnly = false; @@ -656,7 +636,7 @@ protected: // 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; @@ -686,16 +666,15 @@ protected: // The mesh used to draw the layer in GLES composition mode mutable Mesh mMesh; - #ifdef USE_HWC2 // HWC items, accessed from the main thread struct HWCInfo { HWCInfo() - : hwc(nullptr), - layer(nullptr), - forceClientComposition(false), - compositionType(HWC2::Composition::Invalid), - clearClientTarget(false) {} + : hwc(nullptr), + layer(nullptr), + forceClientComposition(false), + compositionType(HWC2::Composition::Invalid), + clearClientTarget(false) {} HWComposer* hwc; HWC2::Layer* layer; -- cgit v1.2.3-59-g8ed1b From eb085e0c579f310e2670204b14b742b68c70bc9e Mon Sep 17 00:00:00 2001 From: David Sodman Date: Thu, 5 Oct 2017 18:49:04 -0700 Subject: Move mSurfaceFlingerConsumer into BufferLayer One of the benefits of splitting the Layer class to have the BufferLayer specific derived class is so that the SurfaceFlingerConsumer can be completely removed from the ColorLayer class (which has no BufferQueue). This change implements that change. Test: Transaction_test.cpp and manual test Change-Id: Ia923c3e0ea366f58de61eca31b444b3332a23e51 --- services/surfaceflinger/BufferLayer.cpp | 175 ++++++++++++++++------ services/surfaceflinger/BufferLayer.h | 33 ++++- services/surfaceflinger/ColorLayer.cpp | 30 ++++ services/surfaceflinger/ColorLayer.h | 21 +++ services/surfaceflinger/Layer.cpp | 248 ++------------------------------ services/surfaceflinger/Layer.h | 37 ++--- 6 files changed, 249 insertions(+), 295 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 8f5dea2691..45093be1a3 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -53,6 +53,7 @@ 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), + mSurfaceFlingerConsumer(nullptr), mTextureName(-1U), mFormat(PIXEL_FORMAT_NONE), mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), @@ -99,6 +100,18 @@ BufferLayer::~BufferLayer() { #endif } +void BufferLayer::useSurfaceDamage() { + if (mFlinger->mForceFullDamage) { + surfaceDamageRegion = Region::INVALID_REGION; + } else { + surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage(); + } +} + +void BufferLayer::useEmptyDamage() { + surfaceDamageRegion.clear(); +} + bool BufferLayer::isProtected() const { const sp& activeBuffer(mActiveBuffer); return (activeBuffer != 0) && (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); @@ -252,6 +265,54 @@ 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(); +} + +bool BufferLayer::shouldPresentNow(const DispSync& dispSync) const { + if (mSidebandStreamChanged || mAutoRefresh) { + return true; + } + + Mutex::Autolock lock(mQueueItemLock); + if (mQueueItems.empty()) { + return false; + } + auto timestamp = mQueueItems[0].mTimestamp; + nsecs_t expectedPresent = mSurfaceFlingerConsumer->computeExpectedPresent(dispSync); + + // Ignore timestamps more than a second in the future + bool isPlausible = timestamp < (expectedPresent + s2ns(1)); + ALOGW_IF(!isPlausible, + "[%s] Timestamp %" PRId64 " seems implausible " + "relative to expectedPresent %" PRId64, + mName.string(), timestamp, expectedPresent); + + bool isDue = timestamp < expectedPresent; + return isDue || !isPlausible; +} + +void BufferLayer::setTransformHint(uint32_t orientation) const { + mSurfaceFlingerConsumer->setTransformHint(orientation); +} + bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { if (mBufferLatched) { Mutex::Autolock lock(mFrameEventHistoryMutex); @@ -260,6 +321,60 @@ bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { mRefreshPending = false; return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; } +bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFence, + const std::shared_ptr& presentFence, + const CompositorTiming& compositorTiming) { + // mFrameLatencyNeeded is true when a new frame was latched for the + // composition. + if (!mFrameLatencyNeeded) return false; + + // Update mFrameEventHistory. + { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, presentFence, + compositorTiming); + } + + // Update mFrameTracker. + nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp(); + mFrameTracker.setDesiredPresentTime(desiredPresentTime); + + std::shared_ptr frameReadyFence = mSurfaceFlingerConsumer->getCurrentFenceTime(); + if (frameReadyFence->isValid()) { + mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); + } else { + // There was no fence for this frame, so assume that it was ready + // to be presented at the desired present time. + mFrameTracker.setFrameReadyTime(desiredPresentTime); + } + + if (presentFence->isValid()) { + 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)); + } + + mFrameTracker.advanceFrame(); + mFrameLatencyNeeded = false; + return true; +} + +std::vector BufferLayer::getOccupancyHistory(bool forceFlush) { + std::vector history; + status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush, &history); + if (result != NO_ERROR) { + ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result); + return {}; + } + return history; +} + +bool BufferLayer::getTransformToDisplayInverse() const { + return mSurfaceFlingerConsumer->getTransformToDisplayInverse(); +} #ifdef USE_HWC2 void BufferLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { @@ -485,6 +600,10 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime return outDirtyRegion; } +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 @@ -529,28 +648,6 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) 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()); @@ -580,26 +677,24 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) } #else -void BufferLayer::setPerFrameData(const sp& hw, +void BufferLayer::setAcquireFence(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); + 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 diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 882649ba70..418f032198 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -64,6 +64,12 @@ public: ~BufferLayer() override; + // 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. + void useSurfaceDamage(); + void useEmptyDamage(); + // ----------------------------------------------------------------------- // Overriden from Layer // ----------------------------------------------------------------------- @@ -99,6 +105,23 @@ 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; + void setTransformHint(uint32_t orientation) const override; + bool onPostComposition(const std::shared_ptr& glDoneFence, + const std::shared_ptr& presentFence, + const CompositorTiming& compositorTiming) override; + std::vector getOccupancyHistory(bool forceFlush) override; + bool getTransformToDisplayInverse() const override; + +public: bool onPreComposition(nsecs_t refreshStartTime) override; #ifdef USE_HWC2 @@ -114,13 +137,15 @@ public: */ Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override; bool isBufferLatched() const override { return mRefreshPending; } + void setDefaultBufferSize(uint32_t w, uint32_t h) override; #ifdef USE_HWC2 - void setPerFrameData(const sp& displayDevice); + void setPerFrameData(const sp& displayDevice) override; #else - void setPerFrameData(const sp& hw, - HWComposer::HWCLayerInterface& layer); + void setAcquireFence(const sp& hw, + HWComposer::HWCLayerInterface& layer) override; #endif + bool isOpaque(const Layer::State& s) const override; private: @@ -160,6 +185,8 @@ public: sp getProducer() const; private: + sp mSurfaceFlingerConsumer; + // 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 diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 500f81f263..8a17f882d0 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -61,6 +61,36 @@ 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(); + Region visible = tr.transform(visibleRegion.intersect(viewport)); + auto hwcId = displayDevice->getHwcDisplayId(); + auto& hwcInfo = mHwcLayers[hwcId]; + auto& hwcLayer = hwcInfo.layer; + auto error = hwcLayer->setVisibleRegion(visible); + + setCompositionType(hwcId, HWC2::Composition::SolidColor); + + 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)); + } + + // 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)); + } +} +#endif + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 89013274af..debd3c3869 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -46,8 +46,29 @@ public: 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*/, + const std::shared_ptr& /*presentFence*/, + const CompositorTiming& /*compositorTiming*/) override { + return false; + } + void setTransformHint(uint32_t /*orientation*/) const override {} + std::vector getOccupancyHistory(bool /*forceFlush*/) override { + return {}; + } + bool getTransformToDisplayInverse() const override { return false; } }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a318a8f46a..c823d67d9f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -69,7 +69,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n : contentDirty(false), sequence(uint32_t(android_atomic_inc(&sSequence))), mFlinger(flinger), - mSurfaceFlingerConsumer(NULL), mPremultipliedAlpha(true), mName(name), mTransactionFlags(0), @@ -153,23 +152,16 @@ Layer::~Layer() { // callbacks // --------------------------------------------------------------------------- +/* + * onLayerDisplayed is only meaningful for BufferLayer, but, is called through + * 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) { - if (mHwcLayers.empty()) { - return; - } - if (mSurfaceFlingerConsumer) { - mSurfaceFlingerConsumer->setReleaseFence(releaseFence); - } -} +void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} #else void Layer::onLayerDisplayed(const sp& /* hw */, - HWComposer::HWCLayerInterface* layer) { - if (layer) { - layer->onDisplayed(); - mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence()); - } -} + HWComposer::HWCLayerInterface* /*layer*/) {} #endif void Layer::onRemovedFromCurrentState() { @@ -191,10 +183,8 @@ void Layer::onRemovedFromCurrentState() { void Layer::onRemoved() { // the layer is removed from SF mLayersPendingRemoval + abandon(); - if (mSurfaceFlingerConsumer) { - mSurfaceFlingerConsumer->abandon(); - } #ifdef USE_HWC2 destroyAllHwcLayers(); #endif @@ -690,105 +680,9 @@ void Layer::forceClientComposition(int32_t hwcId) { mHwcLayers[hwcId].forceClientComposition = true; } - -void Layer::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); - - 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)); - } - - // 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 Layer::setPerFrameData(const sp& hw, - HWComposer::HWCLayerInterface& layer) { + 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. @@ -810,6 +704,7 @@ void Layer::setPerFrameData(const sp& hw, } #endif + #ifdef USE_HWC2 void Layer::updateCursorPosition(const sp& displayDevice) { auto hwcId = displayDevice->getHwcDisplayId(); @@ -844,26 +739,6 @@ void Layer::updateCursorPosition(const sp& displayDevice) { static_cast(error)); } #else -void Layer::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); -} - Rect Layer::getPosition(const sp& hw) { // this gives us only the "orientation" component of the transform const State& s(getCurrentState()); @@ -1176,7 +1051,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h); - if (mSurfaceFlingerConsumer && sizeChanged) { + if (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" @@ -1192,7 +1067,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { // record the new size, form this point on, when the client request // a buffer, it'll get the new size. - mSurfaceFlingerConsumer->setDefaultBufferSize(c.requested.w, c.requested.h); + setDefaultBufferSize(c.requested.w, c.requested.h); } // Don't let Layer::doTransaction update the drawing state @@ -1527,86 +1402,11 @@ void Layer::deferTransactionUntil(const sp& barrierHandle, uint64_t fra deferTransactionUntil(handle->owner.promote(), frameNumber); } -void Layer::useSurfaceDamage() { - if (mFlinger->mForceFullDamage) { - surfaceDamageRegion = Region::INVALID_REGION; - } else { - surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage(); - } -} - -void Layer::useEmptyDamage() { - surfaceDamageRegion.clear(); -} // ---------------------------------------------------------------------------- // pageflip handling... // ---------------------------------------------------------------------------- -bool Layer::shouldPresentNow(const DispSync& dispSync) const { - if (mSidebandStreamChanged || mAutoRefresh) { - return true; - } - - Mutex::Autolock lock(mQueueItemLock); - if (mQueueItems.empty()) { - return false; - } - auto timestamp = mQueueItems[0].mTimestamp; - nsecs_t expectedPresent = mSurfaceFlingerConsumer->computeExpectedPresent(dispSync); - - // Ignore timestamps more than a second in the future - bool isPlausible = timestamp < (expectedPresent + s2ns(1)); - ALOGW_IF(!isPlausible, - "[%s] Timestamp %" PRId64 " seems implausible " - "relative to expectedPresent %" PRId64, - mName.string(), timestamp, expectedPresent); - - bool isDue = timestamp < expectedPresent; - return isDue || !isPlausible; -} - -bool Layer::onPostComposition(const std::shared_ptr& glDoneFence, - const std::shared_ptr& presentFence, - const CompositorTiming& compositorTiming) { - // mFrameLatencyNeeded is true when a new frame was latched for the - // composition. - if (!mFrameLatencyNeeded) return false; - - // Update mFrameEventHistory. - { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, presentFence, - compositorTiming); - } - - // Update mFrameTracker. - nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp(); - mFrameTracker.setDesiredPresentTime(desiredPresentTime); - - std::shared_ptr frameReadyFence = mSurfaceFlingerConsumer->getCurrentFenceTime(); - if (frameReadyFence->isValid()) { - mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); - } else { - // There was no fence for this frame, so assume that it was ready - // to be presented at the desired present time. - mFrameTracker.setFrameReadyTime(desiredPresentTime); - } - - if (presentFence->isValid()) { - 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)); - } - - mFrameTracker.advanceFrame(); - mFrameLatencyNeeded = false; - return true; -} - bool Layer::isHiddenByPolicy() const { const Layer::State& s(mDrawingState); const auto& parent = mDrawingParent.promote(); @@ -1641,9 +1441,7 @@ void Layer::updateTransformHint(const sp& hw) const { orientation = 0; } } - if (mSurfaceFlingerConsumer) { - mSurfaceFlingerConsumer->setTransformHint(orientation); - } + setTransformHint(orientation); } // ---------------------------------------------------------------------------- @@ -1788,26 +1586,6 @@ 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) { - ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result); - return {}; - } - return history; -} - -bool Layer::getTransformToDisplayInverse() const { - if (mSurfaceFlingerConsumer) { - return mSurfaceFlingerConsumer->getTransformToDisplayInverse(); - } - return false; -} - size_t Layer::getChildrenCount() const { size_t count = 0; for (const sp& child : mCurrentChildren) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index db94a31c5e..004d22057b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -42,7 +42,6 @@ #include "LayerVector.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" -#include "SurfaceFlingerConsumer.h" #include "Transform.h" #include @@ -230,8 +229,8 @@ public: // 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. - void useSurfaceDamage(); - void useEmptyDamage(); + virtual void useSurfaceDamage() = 0; + virtual void useEmptyDamage() = 0; uint32_t getTransactionFlags(uint32_t flags); uint32_t setTransactionFlags(uint32_t flags); @@ -294,10 +293,12 @@ protected: bool useIdentityTransform) const = 0; 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); - void setPerFrameData(const sp& displayDevice); + virtual void setPerFrameData(const sp& displayDevice) = 0; // callIntoHwc exists so we can update our local state and call // acceptDisplayChanges without unnecessarily updating the device's state @@ -309,8 +310,8 @@ public: #else void setGeometry(const sp& hw, HWComposer::HWCLayerInterface& layer); void setPerFrameData(const sp& hw, HWComposer::HWCLayerInterface& layer); - void setAcquireFence(const sp& hw, - HWComposer::HWCLayerInterface& layer); + virtual void setAcquireFence(const sp& hw, + HWComposer::HWCLayerInterface& layer) = 0; Rect getPosition(const sp& hw); #endif @@ -318,12 +319,16 @@ public: * called after page-flip */ #ifdef USE_HWC2 - void onLayerDisplayed(const sp& releaseFence); + virtual void onLayerDisplayed(const sp& releaseFence); #else - void onLayerDisplayed(const sp& hw, HWComposer::HWCLayerInterface* layer); + virtual void onLayerDisplayed(const sp& hw, + HWComposer::HWCLayerInterface* layer); #endif - bool shouldPresentNow(const DispSync& dispSync) const; + virtual void abandon() = 0; + + virtual bool shouldPresentNow(const DispSync& dispSync) const = 0; + virtual void setTransformHint(uint32_t orientation) const = 0; /* * called before composition. @@ -335,9 +340,9 @@ public: * called after composition. * returns true if the layer latched a new buffer this frame. */ - bool onPostComposition(const std::shared_ptr& glDoneFence, - const std::shared_ptr& presentFence, - const CompositorTiming& compositorTiming); + virtual bool onPostComposition(const std::shared_ptr& glDoneFence, + const std::shared_ptr& presentFence, + const CompositorTiming& compositorTiming) = 0; #ifdef USE_HWC2 // If a buffer was replaced this frame, release the former buffer @@ -461,13 +466,13 @@ public: void logFrameStats(); void getFrameStats(FrameStats* outStats) const; - std::vector getOccupancyHistory(bool forceFlush); + virtual std::vector getOccupancyHistory(bool forceFlush) = 0; void onDisconnect(); void addAndGetFrameTimestamps(const NewFrameEventsEntry* newEntry, FrameEventHistoryDelta* outDelta); - bool getTransformToDisplayInverse() const; + virtual bool getTransformToDisplayInverse() const = 0; Transform getTransform() const; @@ -524,6 +529,7 @@ protected: virtual void onFirstRef(); friend class SurfaceInterceptor; + void commitTransaction(const State& stateToCommit); uint32_t getEffectiveUsage(uint32_t usage) const; @@ -545,7 +551,6 @@ protected: void addZOrderRelative(const wp& relative); void removeZOrderRelative(const wp& relative); -protected: class SyncPoint { public: explicit SyncPoint(uint64_t frameNumber) @@ -617,8 +622,6 @@ public: protected: // ----------------------------------------------------------------------- - // constants - sp mSurfaceFlingerConsumer; bool mPremultipliedAlpha; String8 mName; String8 mTransactionName; // A cached version of "TX - " + mName for systraces -- cgit v1.2.3-59-g8ed1b From bf32499a90b40e102c59d588f2ee34d9a67e5664 Mon Sep 17 00:00:00 2001 From: Joel Galenson Date: Mon, 6 Nov 2017 11:04:12 -0800 Subject: Fix surfaceflinger on integer sanitized builds. Refactors unsigned integer overflows in traverseInReverseZOrder to fix integer overflow sanitized builds. Test: Compiled and checked output from sanitizer. Bug: 30969751 Change-Id: I46299e7044d360e35ca35a5448b34e4299a500b7 --- services/surfaceflinger/Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c823d67d9f..c1f1ef7644 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1750,7 +1750,7 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, LayerVector list = makeTraversalList(stateSet); int32_t i = 0; - for (i = list.size() - 1; i >= 0; i--) { + for (i = int32_t(list.size()) - 1; i >= 0; i--) { const auto& relative = list[i]; if (relative->getZ() < 0) { break; -- 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/Layer.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/Layer.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 7f619b2350d46eede639efa13d7ac3697551b2cc Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 6 Nov 2017 12:56:35 -0800 Subject: SurfaceFlinger: Ensure relatives are not detached with children. A misapplication of traverseInZOrder...unfortunately we will have to watch out for this. This code was also mistakenly accessing mDrawingState. Test: Transaction_test.cpp Change-Id: I6aa51885f52edff89f1ed5512408bf0a5a227af5 --- services/surfaceflinger/Layer.cpp | 11 +++---- services/surfaceflinger/tests/Transaction_test.cpp | 37 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 80987a4f91..22a72f248d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1661,17 +1661,14 @@ bool Layer::reparent(const sp& newParentHandle) { } bool Layer::detachChildren() { - traverseInZOrder(LayerVector::StateSet::Drawing, [this](Layer* child) { - if (child == this) { - return; - } - + for (const sp& child : mCurrentChildren) { sp parentClient = mClientRef.promote(); sp client(child->mClientRef.promote()); if (client != nullptr && parentClient != client) { - client->detachLayer(child); + client->detachLayer(child.get()); + child->detachChildren(); } - }); + } return true; } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 16a16a53b1..57a55fde45 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -258,6 +258,43 @@ protected: sp mSyncSurfaceControl; }; +TEST_F(LayerUpdateTest, RelativesAreNotDetached) { + sp sc; + + sp relative = mComposerClient->createSurface( + String8("relativeTestSurface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0); + fillSurfaceRGBA8(relative, 10, 10, 10); + waitForPostedBuffers(); + + Transaction{}.setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1) + .setPosition(relative, 64, 64) + .apply(); + + { + // The relative should be on top of the FG control. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(64, 64, 10, 10, 10); + } + Transaction{}.detachChildren(mFGSurfaceControl) + .apply(); + + { + // Nothing should change at this point. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(64, 64, 10, 10, 10); + } + + Transaction{}.hide(relative) + .apply(); + + { + // Ensure that the relative was actually hidden, rather than + // being left in the detached but visible state. + ScreenCapture::captureScreen(&sc); + sc->expectFGColor(64, 64); + } +} + TEST_F(LayerUpdateTest, LayerMoveWorks) { sp sc; { -- 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/Layer.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/Layer.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/Layer.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/Layer.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 9eeae69005ef9a774bde19195b9c06eba7e463c2 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Thu, 2 Nov 2017 10:53:32 -0700 Subject: Surfaceflinger: Create LayerBE data class Split Layer class into a backend and front-end 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: I01d217468ea6008eb46cc3a225d47e1e0b90865a --- services/surfaceflinger/BufferLayer.cpp | 57 ++++++++++++++++++++------------- services/surfaceflinger/Layer.cpp | 31 +++++++++++------- services/surfaceflinger/Layer.h | 16 +++++++-- 3 files changed, 69 insertions(+), 35 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 4e214d1b74..a33ef2cd94 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -249,7 +249,8 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, } // Set things up for texturing. - mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight()); + mTexture.setDimensions(mActiveBuffer->getWidth(), + mActiveBuffer->getHeight()); mTexture.setFiltering(useFiltering); mTexture.setMatrix(textureMatrix); @@ -299,10 +300,12 @@ void BufferLayer::setTransformHint(uint32_t orientation) const { bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { if (mBufferLatched) { Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); + mFrameEventHistory.addPreComposition(mCurrentFrameNumber, + refreshStartTime); } mRefreshPending = false; - return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; + return mQueuedFrames > 0 || mSidebandStreamChanged || + mAutoRefresh; } bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, @@ -314,8 +317,8 @@ bool BufferLayer::onPostComposition(const std::shared_ptr& glDoneFenc // Update mFrameEventHistory. { Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, presentFence, - compositorTiming); + mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, + presentFence, compositorTiming); } // Update mFrameTracker. @@ -429,11 +432,12 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // buffer mode. bool queuedBuffer = false; LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, - getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, - mFreezeGeometryUpdates); + getProducerStickyTransform() != 0, mName.string(), + mOverrideScalingMode, mFreezeGeometryUpdates); status_t updateResult = - mSurfaceFlingerConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync, &mAutoRefresh, - &queuedBuffer, mLastFrameNumberReceived); + 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. @@ -486,12 +490,14 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // Decrement the queued-frames count. Signal another event if we // have more frames pending. - if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) || mAutoRefresh) { + if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) || + mAutoRefresh) { mFlinger->signalLayerUpdate(); } // update the active buffer - mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(&mActiveBufferSlot); + mActiveBuffer = + mSurfaceFlingerConsumer->getCurrentBuffer(&mActiveBufferSlot); if (mActiveBuffer == NULL) { // this can only happen if the very first buffer was rejected. return outDirtyRegion; @@ -519,7 +525,8 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime Rect crop(mSurfaceFlingerConsumer->getCurrentCrop()); const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform()); const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode()); - if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || + if ((crop != mCurrentCrop) || + (transform != mCurrentTransform) || (scalingMode != mCurrentScalingMode)) { mCurrentCrop = crop; mCurrentTransform = transform; @@ -605,7 +612,8 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) 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)); + mSidebandStream->handle(), to_string(error).c_str(), + static_cast(error)); } return; } @@ -628,13 +636,15 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) uint32_t hwcSlot = 0; sp hwcBuffer; - hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &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)); + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), + mActiveBuffer->handle, to_string(error).c_str(), + static_cast(error)); } } @@ -688,7 +698,8 @@ void BufferLayer::onFrameAvailable(const BufferItem& item) { // Ensure that callbacks are handled in order while (item.mFrameNumber != mLastFrameNumberReceived + 1) { - status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); + status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, + ms2ns(500)); if (result != NO_ERROR) { ALOGE("[%s] Timed out waiting on callback", mName.string()); } @@ -711,7 +722,8 @@ void BufferLayer::onFrameReplaced(const BufferItem& item) { // Ensure that callbacks are handled in order while (item.mFrameNumber != mLastFrameNumberReceived + 1) { - status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); + status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, + ms2ns(500)); if (result != NO_ERROR) { ALOGE("[%s] Timed out waiting on callback", mName.string()); } @@ -765,7 +777,7 @@ bool BufferLayer::getOpacityForFormat(uint32_t format) { void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { const State& s(getDrawingState()); - computeGeometry(renderArea, mMesh, useIdentityTransform); + computeGeometry(renderArea, getBE().mMesh, useIdentityTransform); /* * NOTE: the way we compute the texture coordinates here produces @@ -802,7 +814,7 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT // 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()); + Mesh::VertexArray texCoords(getBE().mMesh.getTexCoordArray()); texCoords[0] = vec2(left, 1.0f - top); texCoords[1] = vec2(left, 1.0f - bottom); texCoords[2] = vec2(right, 1.0f - bottom); @@ -812,7 +824,7 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */, getColor()); engine.setSourceDataSpace(mCurrentState.dataSpace); - engine.drawMesh(mMesh); + engine.drawMesh(getBE().mMesh); engine.disableBlending(); } @@ -866,7 +878,8 @@ bool BufferLayer::headFenceHasSignaled() const { // able to be latched. To avoid this, grab this buffer anyway. return true; } - return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; + return mQueueItems[0].mFenceTime->getSignalTime() != + Fence::SIGNAL_TIME_PENDING; } uint32_t BufferLayer::getEffectiveScalingMode() const { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 3be7f47b34..e29132dc8b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -62,6 +62,11 @@ namespace android { +LayerBE::LayerBE() + : mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { +} + + int32_t Layer::sSequence = 1; Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, @@ -84,7 +89,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mFrameLatencyNeeded(false), mFiltering(false), mNeedsFiltering(false), - mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2), mProtectedByApp(false), mClientRef(client), mPotentialCursor(false), @@ -133,6 +137,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n CompositorTiming compositorTiming; flinger->getCompositorTiming(&compositorTiming); mFrameEventHistory.initializeCompositorTiming(compositorTiming); + } void Layer::onFirstRef() {} @@ -204,7 +209,8 @@ sp Layer::getHandle() { // --------------------------------------------------------------------------- bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) { - LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, "Already have a layer for hwcId %d", 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; @@ -634,7 +640,8 @@ bool Layer::getForceClientComposition(int32_t hwcId) { void Layer::updateCursorPosition(const sp& displayDevice) { auto hwcId = displayDevice->getHwcDisplayId(); - if (mHwcLayers.count(hwcId) == 0 || getCompositionType(hwcId) != HWC2::Composition::Cursor) { + if (mHwcLayers.count(hwcId) == 0 || + getCompositionType(hwcId) != HWC2::Composition::Cursor) { return; } @@ -657,7 +664,8 @@ void Layer::updateCursorPosition(const sp& displayDevice) { auto& displayTransform(displayDevice->getTransform()); auto position = displayTransform.transform(frame); - auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left, position.top); + auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left, + position.top); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " "to (%d, %d): %s (%d)", @@ -684,9 +692,9 @@ 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()); - computeGeometry(renderArea, mMesh, false); + computeGeometry(renderArea, getBE().mMesh, false); engine.setupFillWithColor(red, green, blue, alpha); - engine.drawMesh(mMesh); + engine.drawMesh(getBE().mMesh); } void Layer::clearWithOpenGL(const RenderArea& renderArea) const { @@ -961,11 +969,12 @@ uint32_t Layer::doTransaction(uint32_t flags) { " requested={ wh={%4u,%4u} }}\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), c.active.w, - c.active.h, c.crop.left, c.crop.top, c.crop.right, c.crop.bottom, - c.crop.getWidth(), c.crop.getHeight(), c.requested.w, c.requested.h, s.active.w, - s.active.h, s.crop.left, s.crop.top, s.crop.right, s.crop.bottom, - s.crop.getWidth(), s.crop.getHeight(), s.requested.w, s.requested.h); + this, getName().string(), mCurrentTransform, + getEffectiveScalingMode(), c.active.w, c.active.h, c.crop.left, c.crop.top, + c.crop.right, c.crop.bottom, c.crop.getWidth(), c.crop.getHeight(), c.requested.w, + c.requested.h, s.active.w, s.active.h, s.crop.left, s.crop.top, s.crop.right, + s.crop.bottom, s.crop.getWidth(), s.crop.getHeight(), s.requested.w, + s.requested.h); // record the new size, form this point on, when the client request // a buffer, it'll get the new size. diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9ea800e197..5dfc963c8b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -65,13 +65,25 @@ class DisplayDevice; class GraphicBuffer; class SurfaceFlinger; class LayerDebugInfo; +class LayerBE; // --------------------------------------------------------------------------- +class LayerBE { +public: + LayerBE(); + + // The mesh used to draw the layer in GLES composition mode + Mesh mMesh; + +}; + class Layer : public virtual RefBase { static int32_t sSequence; public: + LayerBE& getBE() { return mBE; } + LayerBE& getBE() const { return mBE; } mutable bool contentDirty; // regions below are in window-manager space Region visibleRegion; @@ -652,8 +664,6 @@ protected: bool mFiltering; // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering; - // The mesh used to draw the layer in GLES composition mode - mutable Mesh mMesh; bool mPendingRemoval = false; @@ -708,6 +718,8 @@ protected: wp mCurrentParent; wp mDrawingParent; + + mutable LayerBE mBE; }; // --------------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From 386c22e70d63ecc8bf6ae3e7c2f623f42fcd8718 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Thu, 9 Nov 2017 16:34:46 -0800 Subject: SF: replicate mSidebandStream in LayerBE Add a copy of mSidebandStream in LayerBE. This is one of the few data items that is replicated in both FE and BE. Test: build Change-Id: Ief98645a4fa178e2606c0c337b3f260a1766597a --- services/surfaceflinger/BufferLayer.cpp | 14 ++++++++------ services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/Layer.h | 2 ++ 3 files changed, 11 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index a33ef2cd94..f37f0abaca 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -115,7 +115,7 @@ bool BufferLayer::isProtected() const { bool BufferLayer::isVisible() const { return !(isHiddenByPolicy()) && getAlpha() > 0.0f && - (mActiveBuffer != NULL || mSidebandStream != NULL); + (mActiveBuffer != NULL || getBE().mSidebandStream != NULL); } bool BufferLayer::isFixedSize() const { @@ -385,7 +385,9 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { // mSidebandStreamChanged was true mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream(); - if (mSidebandStream != NULL) { + // replicated in LayerBE until FE/BE is ready to be synchronized + getBE().mSidebandStream = mSidebandStream; + if (getBE().mSidebandStream != NULL) { setTransactionFlags(eTransactionNeeded); mFlinger->setTransactionFlags(eTraversalNeeded); } @@ -606,13 +608,13 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) } // Sideband layers - if (mSidebandStream.get()) { + if (getBE().mSidebandStream.get()) { setCompositionType(hwcId, HWC2::Composition::Sideband); ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = hwcLayer->setSidebandStream(mSidebandStream->handle()); + error = hwcLayer->setSidebandStream(getBE().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(), + getBE().mSidebandStream->handle(), to_string(error).c_str(), static_cast(error)); } return; @@ -651,7 +653,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) 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)) { + if ((getBE().mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) { return false; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e29132dc8b..f4eace8641 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1002,7 +1002,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) && (mActiveBuffer != nullptr); if (!isFixedSize()) { - if (resizePending && mSidebandStream == NULL) { + if (resizePending && getBE().mSidebandStream == NULL) { flags |= eDontUpdateGeometryState; } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5dfc963c8b..b5638e0072 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -73,6 +73,8 @@ class LayerBE { public: LayerBE(); + sp mSidebandStream; + // The mesh used to draw the layer in GLES composition mode Mesh mMesh; -- cgit v1.2.3-59-g8ed1b From 6f65f3e7caab86a76419e7c1d1c787634a0852d8 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Fri, 3 Nov 2017 14:28:09 -0700 Subject: SF: mHwcLayers to LayerBE Move mHwcLayers to LayerBE Test: build Change-Id: I16918223d02ae8017656fa1385ed58bbb21aa688 --- services/surfaceflinger/BufferLayer.cpp | 4 +-- services/surfaceflinger/ColorLayer.cpp | 2 +- services/surfaceflinger/Layer.cpp | 56 ++++++++++++++++---------------- services/surfaceflinger/Layer.h | 57 +++++++++++++++++---------------- 4 files changed, 60 insertions(+), 59 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index f37f0abaca..2fa17e9d44 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -88,7 +88,7 @@ BufferLayer::~BufferLayer() { } mFlinger->deleteTextureAsync(mTextureName); - if (!mHwcLayers.empty()) { + if (!getBE().mHwcLayers.empty()) { ALOGE("Found stale hardware composer layers when destroying " "surface flinger layer %s", mName.string()); @@ -591,7 +591,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) const auto& viewport = displayDevice->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = mHwcLayers[hwcId]; + auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); if (error != HWC2::Error::None) { diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 292e1a7350..b784c8d956 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -66,7 +66,7 @@ void ColorLayer::setPerFrameData(const sp& displayDevice) { const auto& viewport = displayDevice->getViewport(); Region visible = tr.transform(visibleRegion.intersect(viewport)); auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = mHwcLayers[hwcId]; + auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; auto error = hwcLayer->setVisibleRegion(visible); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f4eace8641..359b64fe72 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -209,42 +209,42 @@ sp Layer::getHandle() { // --------------------------------------------------------------------------- bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) { - LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, + LOG_ALWAYS_FATAL_IF(getBE().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]; + LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[hwcId]; hwcInfo.hwc = hwc; hwcInfo.layer = layer; layer->setLayerDestroyedListener( - [this, hwcId](HWC2::Layer* /*layer*/) { mHwcLayers.erase(hwcId); }); + [this, hwcId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(hwcId); }); return true; } bool Layer::destroyHwcLayer(int32_t hwcId) { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { return false; } - auto& hwcInfo = mHwcLayers[hwcId]; + auto& hwcInfo = getBE().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"); - + LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0, + "Stale layer entry in getBE().mHwcLayers"); return true; } void Layer::destroyAllHwcLayers() { - size_t numLayers = mHwcLayers.size(); + size_t numLayers = getBE().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(getBE().mHwcLayers.empty(), "destroyAllHwcLayers failed"); + destroyHwcLayer(getBE().mHwcLayers.begin()->first); } - LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(), + LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(), "All hardware composer layers should have been destroyed"); } @@ -465,7 +465,7 @@ FloatRect Layer::computeCrop(const sp& hw) const { void Layer::setGeometry(const sp& displayDevice, uint32_t z) { const auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = mHwcLayers[hwcId]; + auto& hwcInfo = getBE().mHwcLayers[hwcId]; // enable this layer hwcInfo.forceClientComposition = false; @@ -621,26 +621,26 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z } void Layer::forceClientComposition(int32_t hwcId) { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId); return; } - mHwcLayers[hwcId].forceClientComposition = true; + getBE().mHwcLayers[hwcId].forceClientComposition = true; } bool Layer::getForceClientComposition(int32_t hwcId) { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("getForceClientComposition: no HWC layer found (%d)", hwcId); return false; } - return mHwcLayers[hwcId].forceClientComposition; + return getBE().mHwcLayers[hwcId].forceClientComposition; } void Layer::updateCursorPosition(const sp& displayDevice) { auto hwcId = displayDevice->getHwcDisplayId(); - if (mHwcLayers.count(hwcId) == 0 || + if (getBE().mHwcLayers.count(hwcId) == 0 || getCompositionType(hwcId) != HWC2::Composition::Cursor) { return; } @@ -664,7 +664,7 @@ void Layer::updateCursorPosition(const sp& displayDevice) { auto& displayTransform(displayDevice->getTransform()); auto position = displayTransform.transform(frame); - auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left, + auto error = getBE().mHwcLayers[hwcId].layer->setCursorPosition(position.left, position.top); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " @@ -702,11 +702,11 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { } void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); return; } - auto& hwcInfo = mHwcLayers[hwcId]; + auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(), static_cast(callIntoHwc)); @@ -730,27 +730,27 @@ HWC2::Composition Layer::getCompositionType(int32_t hwcId) const { // have a HWC counterpart, then it will always be Client return HWC2::Composition::Client; } - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("getCompositionType called with an invalid HWC layer"); return HWC2::Composition::Invalid; } - return mHwcLayers.at(hwcId).compositionType; + return getBE().mHwcLayers.at(hwcId).compositionType; } void Layer::setClearClientTarget(int32_t hwcId, bool clear) { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("setClearClientTarget called without a valid HWC layer"); return; } - mHwcLayers[hwcId].clearClientTarget = clear; + getBE().mHwcLayers[hwcId].clearClientTarget = clear; } bool Layer::getClearClientTarget(int32_t hwcId) const { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("getClearClientTarget called without a valid HWC layer"); return false; } - return mHwcLayers.at(hwcId).clearClientTarget; + return getBE().mHwcLayers.at(hwcId).clearClientTarget; } bool Layer::addSyncPoint(const std::shared_ptr& point) { @@ -1432,7 +1432,7 @@ void Layer::miniDumpHeader(String8& result) { } void Layer::miniDump(String8& result, int32_t hwcId) const { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { return; } @@ -1450,7 +1450,7 @@ void Layer::miniDump(String8& result, int32_t hwcId) const { result.appendFormat(" %s\n", name.string()); const Layer::State& layerState(getDrawingState()); - const HWCInfo& hwcInfo = mHwcLayers.at(hwcId); + const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId); result.appendFormat(" %10d | ", layerState.z); result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str()); const Rect& frame = hwcInfo.displayFrame; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b5638e0072..b7b7a3a828 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -78,6 +78,30 @@ public: // The mesh used to draw the layer in GLES composition mode Mesh mMesh; + // HWC items, accessed from the main thread + struct HWCInfo { + HWCInfo() + : hwc(nullptr), + layer(nullptr), + forceClientComposition(false), + compositionType(HWC2::Composition::Invalid), + clearClientTarget(false) {} + + HWComposer* hwc; + HWC2::Layer* layer; + bool forceClientComposition; + HWC2::Composition compositionType; + bool clearClientTarget; + Rect displayFrame; + FloatRect sourceCrop; + HWComposerBufferCache bufferCache; + }; + + // A layer can be attached to multiple displays when operating in mirror mode + // (a.k.a: when several displays are attached with equal layerStack). In this + // 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; }; class Layer : public virtual RefBase { @@ -431,13 +455,15 @@ public: bool destroyHwcLayer(int32_t hwcId); void destroyAllHwcLayers(); - bool hasHwcLayer(int32_t hwcId) { return mHwcLayers.count(hwcId) > 0; } + bool hasHwcLayer(int32_t hwcId) { + return getBE().mHwcLayers.count(hwcId) > 0; + } HWC2::Layer* getHwcLayer(int32_t hwcId) { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { return nullptr; } - return mHwcLayers[hwcId].layer; + return getBE().mHwcLayers[hwcId].layer; } // ----------------------------------------------------------------------- @@ -669,31 +695,6 @@ protected: bool mPendingRemoval = false; - // HWC items, accessed from the main thread - struct HWCInfo { - HWCInfo() - : hwc(nullptr), - layer(nullptr), - forceClientComposition(false), - compositionType(HWC2::Composition::Invalid), - clearClientTarget(false) {} - - HWComposer* hwc; - HWC2::Layer* layer; - bool forceClientComposition; - HWC2::Composition compositionType; - bool clearClientTarget; - Rect displayFrame; - FloatRect sourceCrop; - HWComposerBufferCache bufferCache; - }; - - // A layer can be attached to multiple displays when operating in mirror mode - // (a.k.a: when several displays are attached with equal layerStack). In this - // 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; - // page-flip thread (currently main thread) bool mProtectedByApp; // application requires protected path to external sink -- cgit v1.2.3-59-g8ed1b From 5b4cffc352f7f5d3711d4b7798a07434a998b2d7 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Thu, 23 Nov 2017 13:20:29 -0800 Subject: SF: replicate mActiveBuffer in LayerBE as mBuffer Replicate mAcitveBuffer in LayerBE as mBuffer Test: build/run Change-Id: Iaec4eeddbf4ca1798a47ecbb6c0b6c82ceb1d27c --- services/surfaceflinger/BufferLayer.cpp | 45 ++++++++++++++++++--------------- services/surfaceflinger/Layer.cpp | 38 +++++++++++++++------------- services/surfaceflinger/Layer.h | 5 ++-- 3 files changed, 47 insertions(+), 41 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 2fa17e9d44..0d947b1fe0 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -109,13 +109,14 @@ void BufferLayer::useEmptyDamage() { } bool BufferLayer::isProtected() const { - const sp& activeBuffer(mActiveBuffer); - return (activeBuffer != 0) && (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); + const sp& buffer(getBE().mBuffer); + return (buffer != 0) && + (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); } bool BufferLayer::isVisible() const { return !(isHiddenByPolicy()) && getAlpha() > 0.0f && - (mActiveBuffer != NULL || getBE().mSidebandStream != NULL); + (getBE().mBuffer != NULL || getBE().mSidebandStream != NULL); } bool BufferLayer::isFixedSize() const { @@ -171,7 +172,7 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const { ATRACE_CALL(); - if (CC_UNLIKELY(mActiveBuffer == 0)) { + if (CC_UNLIKELY(getBE().mBuffer == 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 @@ -249,8 +250,8 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, } // Set things up for texturing. - mTexture.setDimensions(mActiveBuffer->getWidth(), - mActiveBuffer->getHeight()); + mTexture.setDimensions(getBE().mBuffer->getWidth(), + getBE().mBuffer->getHeight()); mTexture.setFiltering(useFiltering); mTexture.setMatrix(textureMatrix); @@ -421,7 +422,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // Capture the old state of the layer for comparisons later const State& s(getDrawingState()); const bool oldOpacity = isOpaque(s); - sp oldActiveBuffer = mActiveBuffer; + sp oldBuffer = getBE().mBuffer; if (!allTransactionsSignaled()) { mFlinger->signalLayerUpdate(); @@ -498,9 +499,11 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime } // update the active buffer - mActiveBuffer = - mSurfaceFlingerConsumer->getCurrentBuffer(&mActiveBufferSlot); - if (mActiveBuffer == NULL) { + getBE().mBuffer = + mSurfaceFlingerConsumer->getCurrentBuffer(&getBE().mBufferSlot); + // replicated in LayerBE until FE/BE is ready to be synchronized + mActiveBuffer = getBE().mBuffer; + if (getBE().mBuffer == NULL) { // this can only happen if the very first buffer was rejected. return outDirtyRegion; } @@ -516,7 +519,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime mRefreshPending = true; mFrameLatencyNeeded = true; - if (oldActiveBuffer == NULL) { + if (oldBuffer == NULL) { // the first time we receive a buffer, we need to trigger a // geometry invalidation. recomputeVisibleRegions = true; @@ -536,16 +539,16 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime 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)) { + if (oldBuffer != NULL) { + uint32_t bufWidth = getBE().mBuffer->getWidth(); + uint32_t bufHeight = getBE().mBuffer->getHeight(); + if (bufWidth != uint32_t(oldBuffer->width) || + bufHeight != uint32_t(oldBuffer->height)) { recomputeVisibleRegions = true; } } - mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); + mCurrentOpacity = getOpacityForFormat(getBE().mBuffer->format); if (oldOpacity != isOpaque(s)) { recomputeVisibleRegions = true; } @@ -638,14 +641,14 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) uint32_t hwcSlot = 0; sp hwcBuffer; - hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, - mActiveBuffer, &hwcSlot, &hwcBuffer); + hwcInfo.bufferCache.getHwcBuffer(getBE().mBufferSlot, + getBE().mBuffer, &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(), + getBE().mBuffer->handle, to_string(error).c_str(), static_cast(error)); } } @@ -653,7 +656,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) 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 ((getBE().mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) { + if ((getBE().mSidebandStream == nullptr) && (getBE().mBuffer == nullptr)) { return false; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 359b64fe72..2a4abcb0a2 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -63,7 +63,9 @@ namespace android { LayerBE::LayerBE() - : mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { + : mBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), + mBuffer(nullptr), + mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { } @@ -255,9 +257,9 @@ Rect Layer::getContentCrop() const { if (!mCurrentCrop.isEmpty()) { // if the buffer crop is defined, we use that crop = mCurrentCrop; - } else if (mActiveBuffer != NULL) { + } else if (getBE().mBuffer != NULL) { // otherwise we use the whole buffer - crop = mActiveBuffer->getBounds(); + crop = getBE().mBuffer->getBounds(); } else { // if we don't have a buffer yet, we use an empty/invalid crop crop.makeInvalid(); @@ -1000,7 +1002,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { // to the old buffer. However in the state where we don't have an old buffer // there is no such concern but we may still be being used as a parent layer. const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) && - (mActiveBuffer != nullptr); + (getBE().mBuffer != nullptr); if (!isFixedSize()) { if (resizePending && getBE().mSidebandStream == NULL) { flags |= eDontUpdateGeometryState; @@ -1399,12 +1401,12 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mMatrix[1][0] = ds.active.transform[1][0]; info.mMatrix[1][1] = ds.active.transform[1][1]; { - sp activeBuffer = getActiveBuffer(); - if (activeBuffer != 0) { - info.mActiveBufferWidth = activeBuffer->getWidth(); - info.mActiveBufferHeight = activeBuffer->getHeight(); - info.mActiveBufferStride = activeBuffer->getStride(); - info.mActiveBufferFormat = activeBuffer->format; + sp buffer = getBE().mBuffer; + if (buffer != 0) { + info.mActiveBufferWidth = buffer->getWidth(); + info.mActiveBufferHeight = buffer->getHeight(); + info.mActiveBufferStride = buffer->getStride(); + info.mActiveBufferFormat = buffer->format; } else { info.mActiveBufferWidth = 0; info.mActiveBufferHeight = 0; @@ -1718,15 +1720,15 @@ Transform Layer::getTransform() const { // for in the transform. We need to mirror this scaling in child surfaces // or we will break the contract where WM can treat child surfaces as // pixels in the parent surface. - if (p->isFixedSize() && p->mActiveBuffer != nullptr) { + if (p->isFixedSize() && p->getBE().mBuffer != nullptr) { int bufferWidth; int bufferHeight; if ((p->mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) == 0) { - bufferWidth = p->mActiveBuffer->getWidth(); - bufferHeight = p->mActiveBuffer->getHeight(); + bufferWidth = p->getBE().mBuffer->getWidth(); + bufferHeight = p->getBE().mBuffer->getHeight(); } else { - bufferHeight = p->mActiveBuffer->getWidth(); - bufferWidth = p->mActiveBuffer->getHeight(); + bufferHeight = p->getBE().mBuffer->getWidth(); + bufferWidth = p->getBE().mBuffer->getHeight(); } float sx = p->getDrawingState().active.w / static_cast(bufferWidth); float sy = p->getDrawingState().active.h / static_cast(bufferHeight); @@ -1826,9 +1828,9 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence); } - auto activeBuffer = getActiveBuffer(); - if (activeBuffer != nullptr) { - LayerProtoHelper::writeToProto(activeBuffer, layerInfo->mutable_active_buffer()); + auto buffer = getBE().mBuffer; + if (buffer != nullptr) { + LayerProtoHelper::writeToProto(buffer, layerInfo->mutable_active_buffer()); } layerInfo->set_queued_frames(getQueuedFrameCount()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b12e34fd11..8ac50943b1 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -70,6 +70,9 @@ class LayerBE { public: LayerBE(); + // main thread + int mBufferSlot; + sp mBuffer; sp mSidebandStream; // The mesh used to draw the layer in GLES composition mode @@ -469,8 +472,6 @@ public: void setFiltering(bool filtering); bool getFiltering() const; - // only for debugging - inline const sp& getActiveBuffer() const { return mActiveBuffer; } inline const State& getDrawingState() const { return mDrawingState; } inline const State& getCurrentState() const { return mCurrentState; } -- cgit v1.2.3-59-g8ed1b From 29abff83bb6e148961c2319add7bd72eb76af3d4 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 4 Dec 2017 13:51:20 -0800 Subject: Optimize layer traversal I found when investigating traces with reported jank from P there was a large amount of time in handleMessageInvalidate but before latchBuffer. The only culprit here could be layer traversal itself. The current algorithm is quite costy requiring producing copies of sp, allocating a new vector, etc (see makeTraversalList). This CL optimizes the case where there are no relatives of the current layer. I found that this does in fact eliminate the new time in handleMessageInvalidate and also reduces onPreComposition. Bug:69852584 Test: Manual, comparison of systrace, relative Z still works. Change-Id: I2d942c1987087aae85decc0480d3622204ed665d --- services/surfaceflinger/Layer.cpp | 45 ++++++++++++++++++++++++++++++++++++--- services/surfaceflinger/Layer.h | 3 ++- 2 files changed, 44 insertions(+), 4 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2a4abcb0a2..298f597f34 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1616,14 +1616,25 @@ int32_t Layer::getZ() const { return mDrawingState.z; } +bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const State& state = useDrawing ? mDrawingState : mCurrentState; + return state.zOrderRelativeOf != nullptr; +} + __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList( - LayerVector::StateSet stateSet) { + LayerVector::StateSet stateSet, bool* outSkipRelativeZUsers) { LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid, "makeTraversalList received invalid stateSet"); const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; + if (state.zOrderRelatives.size() == 0) { + *outSkipRelativeZUsers = true; + return children; + } + LayerVector traverse; for (const wp& weakRelative : state.zOrderRelatives) { sp strongRelative = weakRelative.promote(); @@ -1647,19 +1658,35 @@ __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::mak * Negatively signed relatives are before 'this' in Z-order. */ void Layer::traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) { - LayerVector list = makeTraversalList(stateSet); + // In the case we have other layers who are using a relative Z to us, makeTraversalList will + // produce a new list for traversing, including our relatives, and not including our children + // who are relatives of another surface. In the case that there are no relative Z, + // makeTraversalList returns our children directly to avoid significant overhead. + // However in this case we need to take the responsibility for filtering children which + // are relatives of another surface here. + bool skipRelativeZUsers = false; + const LayerVector list = makeTraversalList(stateSet, &skipRelativeZUsers); size_t i = 0; for (; i < list.size(); i++) { const auto& relative = list[i]; + if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) { + continue; + } + if (relative->getZ() >= 0) { break; } relative->traverseInZOrder(stateSet, visitor); } + visitor(this); for (; i < list.size(); i++) { const auto& relative = list[i]; + + if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) { + continue; + } relative->traverseInZOrder(stateSet, visitor); } } @@ -1669,11 +1696,18 @@ void Layer::traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector:: */ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) { - LayerVector list = makeTraversalList(stateSet); + // See traverseInZOrder for documentation. + bool skipRelativeZUsers = false; + LayerVector list = makeTraversalList(stateSet, &skipRelativeZUsers); int32_t i = 0; for (i = int32_t(list.size()) - 1; i >= 0; i--) { const auto& relative = list[i]; + + if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) { + continue; + } + if (relative->getZ() < 0) { break; } @@ -1682,6 +1716,11 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, visitor(this); for (; i >= 0; i--) { const auto& relative = list[i]; + + if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) { + continue; + } + relative->traverseInReverseZOrder(stateSet, visitor); } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8ac50943b1..7c6bc59cfa 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -571,7 +571,7 @@ protected: void setParent(const sp& layer); - LayerVector makeTraversalList(LayerVector::StateSet stateSet); + LayerVector makeTraversalList(LayerVector::StateSet stateSet, bool* outSkipRelativeZUsers); void addZOrderRelative(const wp& relative); void removeZOrderRelative(const wp& relative); @@ -645,6 +645,7 @@ public: protected: // ----------------------------------------------------------------------- + bool usingRelativeZ(LayerVector::StateSet stateSet); bool mPremultipliedAlpha; String8 mName; -- cgit v1.2.3-59-g8ed1b From 0cc69188196037c06127c0bc56c516069dbaa558 Mon Sep 17 00:00:00 2001 From: David Sodman Date: Fri, 17 Nov 2017 12:12:07 -0800 Subject: SF: Add CompositionInfo to LayerBE Add CompositionInfo structure to LayerBE that tracks the actual data that will be used by SurfaceFlinger to compose a frame Test: Build and run manually Change-Id: I2523de430bb14f9d8f149ba011b25a7a470eae2d --- services/surfaceflinger/BufferLayer.cpp | 44 ++++++++++++++++----------------- services/surfaceflinger/Layer.cpp | 27 +++++++++----------- services/surfaceflinger/Layer.h | 36 +++++++++++++++++++++++---- 3 files changed, 65 insertions(+), 42 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 0d947b1fe0..e8f4150135 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -109,14 +109,14 @@ void BufferLayer::useEmptyDamage() { } bool BufferLayer::isProtected() const { - const sp& buffer(getBE().mBuffer); + const sp& buffer(getBE().compositionInfo.mBuffer); return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); } bool BufferLayer::isVisible() const { return !(isHiddenByPolicy()) && getAlpha() > 0.0f && - (getBE().mBuffer != NULL || getBE().mSidebandStream != NULL); + (getBE().compositionInfo.mBuffer != NULL || getBE().compositionInfo.hwc.sidebandStream != NULL); } bool BufferLayer::isFixedSize() const { @@ -172,7 +172,7 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const { ATRACE_CALL(); - if (CC_UNLIKELY(getBE().mBuffer == 0)) { + if (CC_UNLIKELY(getBE().compositionInfo.mBuffer == 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 @@ -250,8 +250,8 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip, } // Set things up for texturing. - mTexture.setDimensions(getBE().mBuffer->getWidth(), - getBE().mBuffer->getHeight()); + mTexture.setDimensions(getBE().compositionInfo.mBuffer->getWidth(), + getBE().compositionInfo.mBuffer->getHeight()); mTexture.setFiltering(useFiltering); mTexture.setMatrix(textureMatrix); @@ -387,8 +387,8 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // mSidebandStreamChanged was true mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream(); // replicated in LayerBE until FE/BE is ready to be synchronized - getBE().mSidebandStream = mSidebandStream; - if (getBE().mSidebandStream != NULL) { + getBE().compositionInfo.hwc.sidebandStream = mSidebandStream; + if (getBE().compositionInfo.hwc.sidebandStream != NULL) { setTransactionFlags(eTransactionNeeded); mFlinger->setTransactionFlags(eTraversalNeeded); } @@ -422,7 +422,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // Capture the old state of the layer for comparisons later const State& s(getDrawingState()); const bool oldOpacity = isOpaque(s); - sp oldBuffer = getBE().mBuffer; + sp oldBuffer = getBE().compositionInfo.mBuffer; if (!allTransactionsSignaled()) { mFlinger->signalLayerUpdate(); @@ -499,11 +499,11 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime } // update the active buffer - getBE().mBuffer = - mSurfaceFlingerConsumer->getCurrentBuffer(&getBE().mBufferSlot); + getBE().compositionInfo.mBuffer = + mSurfaceFlingerConsumer->getCurrentBuffer(&getBE().compositionInfo.mBufferSlot); // replicated in LayerBE until FE/BE is ready to be synchronized - mActiveBuffer = getBE().mBuffer; - if (getBE().mBuffer == NULL) { + mActiveBuffer = getBE().compositionInfo.mBuffer; + if (getBE().compositionInfo.mBuffer == NULL) { // this can only happen if the very first buffer was rejected. return outDirtyRegion; } @@ -540,15 +540,15 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime } if (oldBuffer != NULL) { - uint32_t bufWidth = getBE().mBuffer->getWidth(); - uint32_t bufHeight = getBE().mBuffer->getHeight(); + uint32_t bufWidth = getBE().compositionInfo.mBuffer->getWidth(); + uint32_t bufHeight = getBE().compositionInfo.mBuffer->getHeight(); if (bufWidth != uint32_t(oldBuffer->width) || bufHeight != uint32_t(oldBuffer->height)) { recomputeVisibleRegions = true; } } - mCurrentOpacity = getOpacityForFormat(getBE().mBuffer->format); + mCurrentOpacity = getOpacityForFormat(getBE().compositionInfo.mBuffer->format); if (oldOpacity != isOpaque(s)) { recomputeVisibleRegions = true; } @@ -611,13 +611,13 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) } // Sideband layers - if (getBE().mSidebandStream.get()) { + if (getBE().compositionInfo.hwc.sidebandStream.get()) { setCompositionType(hwcId, HWC2::Composition::Sideband); ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = hwcLayer->setSidebandStream(getBE().mSidebandStream->handle()); + error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle()); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), - getBE().mSidebandStream->handle(), to_string(error).c_str(), + getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(), static_cast(error)); } return; @@ -641,14 +641,14 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) uint32_t hwcSlot = 0; sp hwcBuffer; - hwcInfo.bufferCache.getHwcBuffer(getBE().mBufferSlot, - getBE().mBuffer, &hwcSlot, &hwcBuffer); + hwcInfo.bufferCache.getHwcBuffer(getBE().compositionInfo.mBufferSlot, + getBE().compositionInfo.mBuffer, &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(), - getBE().mBuffer->handle, to_string(error).c_str(), + getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(), static_cast(error)); } } @@ -656,7 +656,7 @@ void BufferLayer::setPerFrameData(const sp& displayDevice) 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 ((getBE().mSidebandStream == nullptr) && (getBE().mBuffer == nullptr)) { + if ((getBE().compositionInfo.hwc.sidebandStream == nullptr) && (getBE().compositionInfo.mBuffer == nullptr)) { return false; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 298f597f34..fa4d289249 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -39,7 +39,6 @@ #include #include -#include #include #include @@ -63,9 +62,7 @@ namespace android { LayerBE::LayerBE() - : mBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), - mBuffer(nullptr), - mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { + : mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { } @@ -257,9 +254,9 @@ Rect Layer::getContentCrop() const { if (!mCurrentCrop.isEmpty()) { // if the buffer crop is defined, we use that crop = mCurrentCrop; - } else if (getBE().mBuffer != NULL) { + } else if (getBE().compositionInfo.mBuffer != NULL) { // otherwise we use the whole buffer - crop = getBE().mBuffer->getBounds(); + crop = getBE().compositionInfo.mBuffer->getBounds(); } else { // if we don't have a buffer yet, we use an empty/invalid crop crop.makeInvalid(); @@ -1002,9 +999,9 @@ uint32_t Layer::doTransaction(uint32_t flags) { // to the old buffer. However in the state where we don't have an old buffer // there is no such concern but we may still be being used as a parent layer. const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) && - (getBE().mBuffer != nullptr); + (getBE().compositionInfo.mBuffer != nullptr); if (!isFixedSize()) { - if (resizePending && getBE().mSidebandStream == NULL) { + if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) { flags |= eDontUpdateGeometryState; } } @@ -1401,7 +1398,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mMatrix[1][0] = ds.active.transform[1][0]; info.mMatrix[1][1] = ds.active.transform[1][1]; { - sp buffer = getBE().mBuffer; + sp buffer = getBE().compositionInfo.mBuffer; if (buffer != 0) { info.mActiveBufferWidth = buffer->getWidth(); info.mActiveBufferHeight = buffer->getHeight(); @@ -1759,15 +1756,15 @@ Transform Layer::getTransform() const { // for in the transform. We need to mirror this scaling in child surfaces // or we will break the contract where WM can treat child surfaces as // pixels in the parent surface. - if (p->isFixedSize() && p->getBE().mBuffer != nullptr) { + if (p->isFixedSize() && p->getBE().compositionInfo.mBuffer != nullptr) { int bufferWidth; int bufferHeight; if ((p->mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) == 0) { - bufferWidth = p->getBE().mBuffer->getWidth(); - bufferHeight = p->getBE().mBuffer->getHeight(); + bufferWidth = p->getBE().compositionInfo.mBuffer->getWidth(); + bufferHeight = p->getBE().compositionInfo.mBuffer->getHeight(); } else { - bufferHeight = p->getBE().mBuffer->getWidth(); - bufferWidth = p->getBE().mBuffer->getHeight(); + bufferHeight = p->getBE().compositionInfo.mBuffer->getWidth(); + bufferWidth = p->getBE().compositionInfo.mBuffer->getHeight(); } float sx = p->getDrawingState().active.w / static_cast(bufferWidth); float sy = p->getDrawingState().active.h / static_cast(bufferHeight); @@ -1867,7 +1864,7 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence); } - auto buffer = getBE().mBuffer; + 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 7c6bc59cfa..9a98e1e2a6 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -31,6 +31,7 @@ #include #include +#include #include @@ -66,15 +67,37 @@ class LayerBE; // --------------------------------------------------------------------------- +struct CompositionInfo { + HWC2::Composition compositionType; + sp mBuffer = nullptr; + int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT; + struct { + HWComposer* hwc; + sp fence; + HWC2::BlendMode blendMode; + Rect displayFrame; + float alpha; + FloatRect sourceCrop; + HWC2::Transform transform; + int z; + int type; + int appId; + Region visibleRegion; + Region surfaceDamage; + sp sidebandStream; + android_dataspace dataspace; + hwc_color_t color; + } hwc; + struct { + RenderEngine* renderEngine; + Mesh* mesh; + } renderEngine; +}; + class LayerBE { public: LayerBE(); - // main thread - int mBufferSlot; - sp mBuffer; - sp mSidebandStream; - // The mesh used to draw the layer in GLES composition mode Mesh mMesh; @@ -102,6 +125,8 @@ public: // 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; + + CompositionInfo compositionInfo; }; class Layer : public virtual RefBase { @@ -339,6 +364,7 @@ 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 -- cgit v1.2.3-59-g8ed1b From 503d2bd9a0c64f90fc321f9d65fc65e592f1fa2b Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 4 Dec 2017 15:49:47 -0800 Subject: Correct setLayer variants. Correct a legitimate bug in setLayer where it would fail to clear a relative layer equal to the new absolute layer. Optimize all the other variants to not trigger rebuilding of layer stacks in the case of redundant Z setting. Test: Existing tests pass. Change-Id: I6559322017a7b8c5510f8ff265216af3d414696a --- services/surfaceflinger/Layer.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 298f597f34..ff5e6f6e36 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1109,8 +1109,9 @@ bool Layer::setChildLayer(const sp& childLayer, int32_t z) { if (childLayer->setLayer(z)) { mCurrentChildren.removeAt(idx); mCurrentChildren.add(childLayer); + return true; } - return true; + return false; } bool Layer::setChildRelativeLayer(const sp& childLayer, @@ -1122,12 +1123,13 @@ bool Layer::setChildRelativeLayer(const sp& childLayer, if (childLayer->setRelativeLayer(relativeToHandle, relativeZ)) { mCurrentChildren.removeAt(idx); mCurrentChildren.add(childLayer); + return true; } - return true; + return false; } bool Layer::setLayer(int32_t z) { - if (mCurrentState.z == z) return false; + if (mCurrentState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false; mCurrentState.sequence++; mCurrentState.z = z; mCurrentState.modified = true; @@ -1158,7 +1160,7 @@ void Layer::addZOrderRelative(const wp& relative) { setTransactionFlags(eTransactionNeeded); } -bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t z) { +bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t relativeZ) { sp handle = static_cast(relativeToHandle.get()); if (handle == nullptr) { return false; @@ -1168,9 +1170,14 @@ bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t z) { return false; } + if (mCurrentState.z == relativeZ && usingRelativeZ(LayerVector::StateSet::Current) && + mCurrentState.zOrderRelativeOf == relative) { + return false; + } + mCurrentState.sequence++; mCurrentState.modified = true; - mCurrentState.z = z; + mCurrentState.z = relativeZ; auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote(); if (oldZOrderRelativeOf != nullptr) { -- cgit v1.2.3-59-g8ed1b From 577c896102ebb13f9496a94674b4ca9cd15fe0ad Mon Sep 17 00:00:00 2001 From: David Sodman Date: Fri, 8 Dec 2017 14:50:53 -0800 Subject: SurfaceFlinger: Move generic dtor logic to Layer Move Layer generic code from BufferLayer destructor to the Layer destructor so that ColorLayer will be able to use it. Bug: 69127378 Test: CTS SurfaceView tests Change-Id: Ie48ee2c3433e80bcae822654d4dc186d09c49c00 --- services/surfaceflinger/BufferLayer.cpp | 11 ----------- services/surfaceflinger/Layer.cpp | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index e8f4150135..7d9d4f6969 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -75,17 +75,6 @@ BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp& client, cons } 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); if (!getBE().mHwcLayers.empty()) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index fa4d289249..13df1e21b4 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -142,6 +142,17 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n void Layer::onFirstRef() {} Layer::~Layer() { + sp c(mClientRef.promote()); + if (c != 0) { + c->detachLayer(this); + } + + for (auto& point : mRemoteSyncPoints) { + point->setTransactionApplied(); + } + for (auto& point : mLocalSyncPoints) { + point->setFrameAvailable(); + } mFrameTracker.logAndResetStats(mName); } -- cgit v1.2.3-59-g8ed1b From 80d611613ef1a9c05a31cd3f47badfd4de9b1418 Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Wed, 20 Dec 2017 15:57:52 -0800 Subject: SF: Switch computeBounds to return FloatRect Switches Layer::computeBounds to return a FloatRect instead of a Rect. During the computation of the bounds, we apply the layer transformation to its nominal dimensions, clip it against its bounds (which are either its parents bounds or the screen bounds), and apply the inverse of the layer transformation. Previously, the intermediate position (after transformation/clip, but before inverse transformation) was stored as Rect, which is to say that it was truncated to integer coordinates. After applying the inverse transformation, this loss of precision can cause glitches where a layer that should be clipped against, e.g., the side of the screen no longer creates a watertight seal against that side. In order to fix this, we now store the intermediate value as a FloatRect and propagate float precision back through computeBounds. The callers of computeBounds tend to then immediately apply the transform again, at which point it is safe to round back to integer. Bug: 64070729 Bug: 66431327 Bug: 69935057 Test: Modified android.view.cts.SurfaceViewSyncTest# testSurfaceViewBigScale no longer produces bogus display frames Change-Id: If5987ca4ad76657f9670a5f59258f896180352e2 --- libs/ui/include/ui/FloatRect.h | 11 +++++++++++ libs/ui/include/ui/Rect.h | 9 +++++++++ services/surfaceflinger/BufferLayer.cpp | 5 +++-- services/surfaceflinger/Layer.cpp | 28 ++++++++++++++++++++-------- services/surfaceflinger/Layer.h | 5 +++-- services/surfaceflinger/Transform.cpp | 21 +++++++++++++++++++++ services/surfaceflinger/Transform.h | 1 + 7 files changed, 68 insertions(+), 12 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/ui/include/ui/FloatRect.h b/libs/ui/include/ui/FloatRect.h index 270675cba2..6a7479a68a 100644 --- a/libs/ui/include/ui/FloatRect.h +++ b/libs/ui/include/ui/FloatRect.h @@ -27,6 +27,17 @@ public: float getWidth() const { return right - left; } float getHeight() const { return bottom - top; } + FloatRect intersect(const FloatRect& other) const { + return { + // Inline to avoid tromping on other min/max defines or adding a + // dependency on STL + (left > other.left) ? left : other.left, + (top > other.top) ? top : other.top, + (right < other.right) ? right : other.right, + (bottom < other.bottom) ? bottom : other.bottom + }; + } + float left = 0.0f; float top = 0.0f; float right = 0.0f; diff --git a/libs/ui/include/ui/Rect.h b/libs/ui/include/ui/Rect.h index 437fc14504..0bec0b7f78 100644 --- a/libs/ui/include/ui/Rect.h +++ b/libs/ui/include/ui/Rect.h @@ -69,6 +69,15 @@ public: bottom = rb.y; } + inline explicit Rect(const FloatRect& floatRect) { + // Ideally we would use std::round, but we don't want to add an STL + // dependency here, so we use an approximation + left = static_cast(floatRect.left + 0.5f); + top = static_cast(floatRect.top + 0.5f); + right = static_cast(floatRect.right + 0.5f); + bottom = static_cast(floatRect.bottom + 0.5f); + } + void makeInvalid(); inline void clear() { diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index b52bef31c7..f16e1bad5d 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -787,16 +787,17 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT * minimal value)? Or, we could make GL behave like HWC -- but this feel * like more of a hack. */ - Rect win(computeBounds()); + const Rect bounds{computeBounds()}; // Rounds from FloatRect Transform t = getTransform(); + Rect win = bounds; 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)) { + if (!win.intersect(bounds, &win)) { win.clear(); } } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 13df1e21b4..a5d0c3a278 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -285,6 +285,14 @@ static Rect reduce(const Rect& win, const Region& exclude) { return Region(win).subtract(exclude).getBounds(); } +static FloatRect reduce(const FloatRect& win, const Region& exclude) { + if (CC_LIKELY(exclude.isEmpty())) { + return win; + } + // Convert through Rect (by rounding) for lack of FloatRegion + return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect(); +} + Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { const Layer::State& s(getDrawingState()); Rect win(s.active.w, s.active.h); @@ -323,12 +331,12 @@ Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { return win; } -Rect Layer::computeBounds() const { +FloatRect Layer::computeBounds() const { const Layer::State& s(getDrawingState()); return computeBounds(s.activeTransparentRegion); } -Rect Layer::computeBounds(const Region& activeTransparentRegion) const { +FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { const Layer::State& s(getDrawingState()); Rect win(s.active.w, s.active.h); @@ -345,14 +353,16 @@ Rect Layer::computeBounds(const Region& activeTransparentRegion) const { } Transform t = getTransform(); + + FloatRect floatWin = win.toFloatRect(); if (p != nullptr) { - win = t.transform(win); - win.intersect(bounds, &win); - win = t.inverse().transform(win); + floatWin = t.transform(floatWin); + floatWin = floatWin.intersect(bounds.toFloatRect()); + floatWin = t.inverse().transform(floatWin); } // subtract the transparent region and snap to the bounds - return reduce(win, activeTransparentRegion); + return reduce(floatWin, activeTransparentRegion); } Rect Layer::computeInitialCrop(const sp& hw) const { @@ -528,7 +538,9 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom)); } - Rect frame(t.transform(computeBounds(activeTransparentRegion))); + // computeBounds returns a FloatRect to provide more accuracy during the + // transformation. We then round upon constructing 'frame'. + Rect frame{t.transform(computeBounds(activeTransparentRegion))}; if (!s.finalCrop.isEmpty()) { if (!frame.intersect(s.finalCrop, &frame)) { frame.clear(); @@ -807,7 +819,7 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, const Layer::State& s(getDrawingState()); const Transform renderAreaTransform(renderArea.getTransform()); const uint32_t height = renderArea.getHeight(); - Rect win = computeBounds(); + FloatRect win = computeBounds(); vec2 lt = vec2(win.left, win.top); vec2 lb = vec2(win.left, win.bottom); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index cf7fc508e8..e44ccf8d57 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -303,8 +304,8 @@ public: } void computeGeometry(const RenderArea& renderArea, Mesh& mesh, bool useIdentityTransform) const; - Rect computeBounds(const Region& activeTransparentRegion) const; - Rect computeBounds() const; + FloatRect computeBounds(const Region& activeTransparentRegion) const; + FloatRect computeBounds() const; int32_t getSequence() const { return sequence; } diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index 37925a1641..e05ed5375e 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -224,6 +224,27 @@ Rect Transform::transform(const Rect& bounds, bool roundOutwards) const return r; } +FloatRect Transform::transform(const FloatRect& bounds) const +{ + vec2 lt(bounds.left, bounds.top); + vec2 rt(bounds.right, bounds.top); + vec2 lb(bounds.left, bounds.bottom); + vec2 rb(bounds.right, bounds.bottom); + + lt = transform(lt); + rt = transform(rt); + lb = transform(lb); + rb = transform(rb); + + FloatRect r; + r.left = min(lt[0], rt[0], lb[0], rb[0]); + r.top = min(lt[1], rt[1], lb[1], rb[1]); + r.right = max(lt[0], rt[0], lb[0], rb[0]); + r.bottom = max(lt[1], rt[1], lb[1], rb[1]); + + return r; +} + Region Transform::transform(const Region& reg) const { Region out; diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h index bfc66eccb9..b11d0576c4 100644 --- a/services/surfaceflinger/Transform.h +++ b/services/surfaceflinger/Transform.h @@ -84,6 +84,7 @@ public: Region transform(const Region& reg) const; Rect transform(const Rect& bounds, bool roundOutwards = false) const; + FloatRect transform(const FloatRect& bounds) const; Transform operator * (const Transform& rhs) const; // assumes the last row is < 0 , 0 , 1 > vec2 transform(const vec2& v) const; -- 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/Layer.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 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/Layer.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 5a96326ee136018ab9bb1cbeec1fd5f9f3a8291a Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Wed, 17 Jan 2018 15:57:44 +0100 Subject: Force client composition if we'd use rotator HWC can only handle a certain range of scaling values, and will fall back into rotator mode otherwise. However, there is an issue at the moment with the rotator that leads to one missed frame when enabling it, and we're better off with GL comp in that case. Add some temporary hack to force GPU composition if we detect that the scaling value is set to a value that would put us into rotator mode. Test: Have some animation with a lot of scaling, observe no jank. Bug: 72106793 Bug: 64674361 Change-Id: I7eb55947179f4347e93caf572cc926ddbec9df9f --- services/surfaceflinger/Layer.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 33f0796ae0..067a09fb5d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -626,9 +626,15 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z transform = Transform(invTransform) * tr * bufferOrientation; } + // STOPSHIP (b/72106793): If we have less than 25% scaling, HWC usually needs to use the rotator + // to handle it. However, there is one guaranteed frame of jank when we switch to using the + // rotator. In the meantime, we force GL composition instead until we have a better fix for the + // HWC issue. + bool extremeScaling = abs(t[0][0]) <= 0.25 || abs(t[1][1]) <= 0.25; + // this gives us only the "orientation" component of the transform const uint32_t orientation = transform.getOrientation(); - if (orientation & Transform::ROT_INVALID) { + if (orientation & Transform::ROT_INVALID || extremeScaling) { // we can only handle simple transformation hwcInfo.forceClientComposition = true; } else { -- 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/Layer.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 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/Layer.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 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/Layer.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 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/Layer.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 f3bd94a776d69730ddb95bbf7104f2fb89d92ae4 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Tue, 27 Mar 2018 15:38:03 +0200 Subject: Revert "Force client composition if we'd use rotator" This reverts commit 5a96326ee136018ab9bb1cbeec1fd5f9f3a8291a. We'll configure the individual devices to avoid rotator for downscaling instead. Bug: 73640835 Bug: 72106793 Change-Id: Ibbf00b21391dc52e9327c090cf2d745495970618 --- services/surfaceflinger/Layer.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 6bd187f820..b56b4e4665 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -628,15 +628,9 @@ void Layer::setGeometry(const sp& displayDevice, uint32_t z transform = Transform(invTransform) * tr * bufferOrientation; } - // STOPSHIP (b/72106793): If we have less than 25% scaling, HWC usually needs to use the rotator - // to handle it. However, there is one guaranteed frame of jank when we switch to using the - // rotator. In the meantime, we force GL composition instead until we have a better fix for the - // HWC issue. - bool extremeScaling = abs(t[0][0]) <= 0.25 || abs(t[1][1]) <= 0.25; - // this gives us only the "orientation" component of the transform const uint32_t orientation = transform.getOrientation(); - if (orientation & Transform::ROT_INVALID || extremeScaling) { + if (orientation & Transform::ROT_INVALID) { // we can only handle simple transformation hwcInfo.forceClientComposition = true; } else { -- 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/Layer.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 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/Layer.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/Layer.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/Layer.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 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/Layer.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 923e7c56cb9a4a611dcc3db904116926ee958ad7 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Mon, 16 Apr 2018 14:16:37 -0700 Subject: [SurfaceFlinger] Make sure data space is set correctly This patch makes sure data space is set correctly for native window. Previously, the data space could be unknown. BUG: 77652630 BUG: 78025830 Test: Build, flash, watch some videos Change-Id: I3096ebaecda35838493e0d5e2efdf141eff0b75e --- services/surfaceflinger/BufferLayer.cpp | 22 +++++++++++++++++++++- services/surfaceflinger/Layer.cpp | 14 ++------------ 2 files changed, 23 insertions(+), 13 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 2aa4cd3578..57f474b9ea 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -515,7 +515,27 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime recomputeVisibleRegions = true; } - setDataSpace(mConsumer->getCurrentDataSpace()); + // 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(); + switch (dataSpace) { + case ui::Dataspace::V0_SRGB: + dataSpace = ui::Dataspace::SRGB; + break; + 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; + } + break; + default: + break; + } + setDataSpace(dataSpace); Rect crop(mConsumer->getCurrentCrop()); const uint32_t transform(mConsumer->getCurrentTransform()); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8c0050ee47..3a71188b37 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1643,19 +1643,9 @@ 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; + return mDrawingState.dataSpace == ui::Dataspace::SRGB || + mDrawingState.dataSpace == ui::Dataspace::SRGB_LINEAR; } void Layer::setParent(const sp& layer) { -- cgit v1.2.3-59-g8ed1b From 4b129c2e3f581ad2d8d18c99dc7b0c5bff3bd348 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 9 Apr 2018 16:19:43 -0700 Subject: Respect relative layer value if in tree when screenshotting. Relative layers need to be screenshotted so the dim layer can be captured in the correct place. However, there are other relative layers that are not in the tree that shouldn't be part of the screenshot. This change allows relative layer value to be handled correctly as long as the layer it's relative to is in the tree to capture. This ensures relative layers in the tree are captured the correct order, but also ignores any relative layers that are not in the tree. Change-Id: If0e0ea1417f01ad1bfe518744ae2b9827009c4c6 Fixes: 77823704 Test: Open app with dialog and go to recents. Dim is screenshotted. Test: Open app with IME and go to recents. IME is not screenshotted. Test: Transaction_test#DontCaptureRelativeOutsideTree, CaptureRelativeInTree --- services/surfaceflinger/Layer.cpp | 75 ++++++++++++++++++---- services/surfaceflinger/Layer.h | 21 ++++++ services/surfaceflinger/tests/Transaction_test.cpp | 52 +++++++++++++++ 3 files changed, 137 insertions(+), 11 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8c0050ee47..2300048f7e 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -1787,27 +1788,79 @@ 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) { +LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, + const std::vector& layersInTree) { + LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid, + "makeTraversalList received invalid stateSet"); const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; + const State& state = useDrawing ? mDrawingState : mCurrentState; + + LayerVector traverse; + for (const wp& weakRelative : state.zOrderRelatives) { + sp strongRelative = weakRelative.promote(); + // Only add relative layers that are also descendents of the top most parent of the tree. + // If a relative layer is not a descendent, then it should be ignored. + if (std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) { + traverse.add(strongRelative); + } + } + + for (const sp& child : children) { + const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState; + // If a layer has a relativeOf layer, only ignore if the layer it's relative to is a + // descendent of the top most parent of the tree. If it's not a descendent, then just add + // the child here since it won't be added later as a relative. + if (std::binary_search(layersInTree.begin(), layersInTree.end(), + childState.zOrderRelativeOf.promote().get())) { + continue; + } + traverse.add(child); + } + + return traverse; +} + +void Layer::traverseChildrenInZOrderInner(const std::vector& layersInTree, + LayerVector::StateSet stateSet, + const LayerVector::Visitor& visitor) { + const LayerVector list = makeChildrenTraversalList(stateSet, layersInTree); size_t i = 0; - for (; i < children.size(); i++) { - const auto& relative = children[i]; + for (; i < list.size(); i++) { + const auto& relative = list[i]; if (relative->getZ() >= 0) { break; } - relative->traverseChildrenInZOrder(stateSet, visitor); + relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); } + visitor(this); - for (; i < children.size(); i++) { - const auto& relative = children[i]; - relative->traverseChildrenInZOrder(stateSet, visitor); + for (; i < list.size(); i++) { + const auto& relative = list[i]; + relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); + } +} + +std::vector Layer::getLayersInTree(LayerVector::StateSet stateSet) { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; + + std::vector layersInTree = {this}; + for (size_t i = 0; i < children.size(); i++) { + const auto& child = children[i]; + std::vector childLayers = child->getLayersInTree(stateSet); + layersInTree.insert(layersInTree.end(), childLayers.cbegin(), childLayers.cend()); } + + return layersInTree; +} + +void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet, + const LayerVector::Visitor& visitor) { + std::vector layersInTree = getLayersInTree(stateSet); + std::sort(layersInTree.begin(), layersInTree.end()); + traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); } Transform Layer::getTransform() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d382a1a173..be3967b2cb 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -51,6 +51,7 @@ #include "RenderEngine/Texture.h" #include +#include using namespace android::surfaceflinger; @@ -564,6 +565,10 @@ public: const LayerVector::Visitor& visitor); void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); + /** + * Traverse only children in z order, ignoring relative layers that are not children of the + * parent. + */ void traverseChildrenInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); @@ -778,6 +783,22 @@ protected: wp mDrawingParent; mutable LayerBE mBE; + +private: + /** + * Returns an unsorted vector of all layers that are part of this tree. + * That includes the current layer and all its descendants. + */ + std::vector getLayersInTree(LayerVector::StateSet stateSet); + /** + * Traverses layers that are part of this tree in the correct z order. + * layersInTree must be sorted before calling this method. + */ + void traverseChildrenInZOrderInner(const std::vector& layersInTree, + LayerVector::StateSet stateSet, + const LayerVector::Visitor& visitor); + LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet, + const std::vector& layersInTree); }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index a0f12f1438..5108279043 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2376,6 +2376,58 @@ TEST_F(ScreenCaptureTest, CaptureTransparent) { mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0}); } +TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp child = + mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + sp relative = mComposerClient->createSurface(String8("Relative surface"), 10, + 10, PIXEL_FORMAT_RGBA_8888, 0); + fillSurfaceRGBA8(child, 200, 200, 200); + fillSurfaceRGBA8(relative, 100, 100, 100); + + SurfaceComposerClient::Transaction() + .show(child) + // Set relative layer above fg layer so should be shown above when computing all layers. + .setRelativeLayer(relative, fgHandle, 1) + .show(relative) + .apply(true); + + // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured. + ScreenCapture::captureLayers(&mCapture, fgHandle); + mCapture->expectFGColor(10, 10); + mCapture->expectChildColor(0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureRelativeInTree) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp child = + mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + sp relative = + mComposerClient->createSurface(String8("Relative surface"), 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(child, 200, 200, 200); + fillSurfaceRGBA8(relative, 100, 100, 100); + + SurfaceComposerClient::Transaction() + .show(child) + // Set relative layer below fg layer but relative to child layer so it should be shown + // above child layer. + .setLayer(relative, -1) + .setRelativeLayer(relative, child->getHandle(), 1) + .show(relative) + .apply(true); + + // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its + // relative value should be taken into account, placing it above child layer. + ScreenCapture::captureLayers(&mCapture, fgHandle); + mCapture->expectFGColor(10, 10); + // Relative layer is showing on top of child layer + mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255}); +} // 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 94c7d3d948beff287eed53e6d841e29e05cad8b3 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 24 Apr 2018 12:30:47 -0700 Subject: SurfaceFlinger: Only update client parent if set. We use the idea of client with parents to allow applications to access SurfaceFlinger as long as they have an original "root" Surface granted to them from the WindowManager. Sometimes the WindowManager may reparent these child surfaces to a new surface, and so we need to update which Surface is providing this grant. However, if a client never had a root surface and is instead relying on ACCESS_SURFACE_FLINGER, e.g. the WindowManager we need to not reparent or we may end up making the client invalid when the Surface dies when we never intended to. Bug: 78301580 Bug: 62536731 Test: Manual repro of b/78301580 Change-Id: Ib18cfe86e1cec3da7808fcd01e2b7ce02bebff6d --- services/surfaceflinger/Client.cpp | 9 +++++++-- services/surfaceflinger/Client.h | 2 +- services/surfaceflinger/Layer.cpp | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index c90024b863..077469b5e1 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -65,9 +65,14 @@ Client::~Client() } } -void Client::setParentLayer(const sp& parentLayer) { +void Client::updateParent(const sp& parentLayer) { Mutex::Autolock _l(mLock); - mParentLayer = parentLayer; + + // If we didn't ever have a parent, then we must instead be + // relying on permissions and we never need a parent. + if (mParentLayer != nullptr) { + mParentLayer = parentLayer; + } } sp Client::getParentLayer(bool* outParentDied) const { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index c7df9f780f..49437ed7fd 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -51,7 +51,7 @@ public: sp getLayerUser(const sp& handle) const; - void setParentLayer(const sp& parentLayer); + void updateParent(const sp& parentLayer); private: // ISurfaceComposerClient interface diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 66ad2f60a6..bbc974de2f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1589,7 +1589,7 @@ bool Layer::reparentChildren(const sp& newParentHandle) { sp client(child->mClientRef.promote()); if (client != nullptr) { - client->setParentLayer(newParent); + client->updateParent(newParent); } } mCurrentChildren.clear(); @@ -1625,7 +1625,7 @@ bool Layer::reparent(const sp& newParentHandle) { sp newParentClient(newParent->mClientRef.promote()); if (client != newParentClient) { - client->setParentLayer(newParent); + client->updateParent(newParent); } return true; -- 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/Layer.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 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/Layer.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 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/Layer.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 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/Layer.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 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/Layer.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 738df02be90749afa30316ff70ef0ed425ceb6f0 Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 31 May 2018 16:11:27 -0700 Subject: Use correct StateSet for LayerVector compare. Currently LayerVector compare function was using the current StateSet. This is incorect since the LayerVector may be created with the intention of sorting the layers by drawing state. Instead, create the LayerVector with a specified StateSet so the compare function always uses the correct state. This fixes an issue where the layers were getting added and sorted by current state z order but the caller expected the order to be by drawing state z order. Change-Id: I7afef556fa72f687bcfeb0a642465488cc72f40b Fixes: 80516823 Test: No longer flicker when IME closes. Logs show correct z order. Merged-In: I7afef556fa72f687bcfeb0a642465488cc72f40b --- services/surfaceflinger/Layer.cpp | 10 +++++----- services/surfaceflinger/LayerVector.cpp | 25 ++++++++++++++++++------- services/surfaceflinger/LayerVector.h | 13 +++++++++---- services/surfaceflinger/SurfaceFlinger.h | 2 +- 4 files changed, 33 insertions(+), 17 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2077598371..618154da7b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -98,8 +98,9 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n mQueueItems(), mLastFrameNumberReceived(0), mAutoRefresh(false), - mFreezeGeometryUpdates(false) { - + mFreezeGeometryUpdates(false), + mCurrentChildren(LayerVector::StateSet::Current), + mDrawingChildren(LayerVector::StateSet::Drawing) { mCurrentCrop.makeInvalid(); uint32_t layerFlags = 0; @@ -138,7 +139,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client, const String8& n CompositorTiming compositorTiming; flinger->getCompositorTiming(&compositorTiming); mFrameEventHistory.initializeCompositorTiming(compositorTiming); - } void Layer::onFirstRef() {} @@ -1691,7 +1691,7 @@ __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::mak return children; } - LayerVector traverse; + LayerVector traverse(stateSet); for (const wp& weakRelative : state.zOrderRelatives) { sp strongRelative = weakRelative.promote(); if (strongRelative != nullptr) { @@ -1789,7 +1789,7 @@ LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; - LayerVector traverse; + LayerVector traverse(stateSet); for (const wp& weakRelative : state.zOrderRelatives) { sp strongRelative = weakRelative.promote(); // Only add relative layers that are also descendents of the top most parent of the tree. diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp index 47156c19d2..84945247a6 100644 --- a/services/surfaceflinger/LayerVector.cpp +++ b/services/surfaceflinger/LayerVector.cpp @@ -19,26 +19,37 @@ namespace android { -LayerVector::LayerVector() = default; +LayerVector::LayerVector(const StateSet stateSet) : mStateSet(stateSet) {} -LayerVector::LayerVector(const LayerVector& rhs) : SortedVector>(rhs) { -} +LayerVector::LayerVector(const LayerVector& rhs, const StateSet stateSet) + : SortedVector>(rhs), mStateSet(stateSet) {} LayerVector::~LayerVector() = default; +// This operator override is needed to prevent mStateSet from getting copied over. +LayerVector& LayerVector::operator=(const LayerVector& rhs) { + SortedVector::operator=(rhs); + return *this; +} + int LayerVector::do_compare(const void* lhs, const void* rhs) const { // sort layers per layer-stack, then by z-order and finally by sequence const auto& l = *reinterpret_cast*>(lhs); const auto& r = *reinterpret_cast*>(rhs); - uint32_t ls = l->getCurrentState().layerStack; - uint32_t rs = r->getCurrentState().layerStack; + const auto& lState = + (mStateSet == StateSet::Current) ? l->getCurrentState() : l->getDrawingState(); + const auto& rState = + (mStateSet == StateSet::Current) ? r->getCurrentState() : r->getDrawingState(); + + uint32_t ls = lState.layerStack; + uint32_t rs = rState.layerStack; if (ls != rs) return (ls > rs) ? 1 : -1; - int32_t lz = l->getCurrentState().z; - int32_t rz = r->getCurrentState().z; + int32_t lz = lState.z; + int32_t rz = rState.z; if (lz != rz) return (lz > rz) ? 1 : -1; diff --git a/services/surfaceflinger/LayerVector.h b/services/surfaceflinger/LayerVector.h index a9adb4113a..88d7711bb8 100644 --- a/services/surfaceflinger/LayerVector.h +++ b/services/surfaceflinger/LayerVector.h @@ -32,22 +32,27 @@ class Layer; */ class LayerVector : public SortedVector> { public: - LayerVector(); - LayerVector(const LayerVector& rhs); - ~LayerVector() override; - enum class StateSet { Invalid, Current, Drawing, }; + explicit LayerVector(const StateSet stateSet); + LayerVector(const LayerVector& rhs, const StateSet stateSet); + ~LayerVector() override; + + LayerVector& operator=(const LayerVector& rhs); + // Sorts layer by layer-stack, Z order, and finally creation order (sequence). int do_compare(const void* lhs, const void* rhs) const override; using Visitor = std::function; void traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const; void traverseInZOrder(StateSet stateSet, const Visitor& visitor) const; + +private: + const StateSet mStateSet; }; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d9cf9461ca..78460add51 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -367,7 +367,7 @@ private: class State { public: - explicit State(LayerVector::StateSet set) : stateSet(set) {} + explicit State(LayerVector::StateSet set) : stateSet(set), layersSortedByZ(set) {} State& operator=(const State& other) { // We explicitly don't copy stateSet so that, e.g., mDrawingState // always uses the Drawing StateSet. -- cgit v1.2.3-59-g8ed1b