1a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include "hardware_composer.h" 2a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 3a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <cutils/properties.h> 4a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <cutils/sched_policy.h> 5a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <fcntl.h> 62251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <log/log.h> 7a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <poll.h> 8b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka#include <stdint.h> 9a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sync/sync.h> 10a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sys/eventfd.h> 11a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sys/prctl.h> 12a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sys/resource.h> 13a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sys/system_properties.h> 14a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sys/timerfd.h> 15b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka#include <sys/types.h> 162251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <time.h> 17a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <unistd.h> 18a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <utils/Trace.h> 19a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 20a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <algorithm> 212251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <chrono> 22a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <functional> 23a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <map> 240b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka#include <sstream> 250b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka#include <string> 26954796e27e89209b38b35779949c243bec490c28John Bates#include <tuple> 27a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <dvr/dvr_display_types.h> 29a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <dvr/performance_client_api.h> 30a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <private/dvr/clock_ns.h> 312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <private/dvr/ion_buffer.h> 32a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 33b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomasusing android::hardware::Return; 34b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomasusing android::hardware::Void; 35b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabakausing android::pdx::ErrorStatus; 36a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkousing android::pdx::LocalHandle; 37b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabakausing android::pdx::Status; 382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakausing android::pdx::rpc::EmptyVariant; 392251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakausing android::pdx::rpc::IfAnyOf; 402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 412251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakausing namespace std::chrono_literals; 42a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 43a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkonamespace android { 44a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkonamespace dvr { 45a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 46a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkonamespace { 47a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 48a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoconst char kDvrPerformanceProperty[] = "sys.dvr.performance"; 49451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabakaconst char kDvrStandaloneProperty[] = "ro.boot.vr"; 50a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 514b78832d7fc3cdd13a20587dfee96d1505916213Luke Songconst char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns"; 52a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 53bfe46a053be03836a060853711b467ed5e10affaSteven Thomasconst char kUseExternalDisplayProperty[] = "persist.vr.use_external_display"; 54bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 55af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas// How long to wait after boot finishes before we turn the display off. 56af33627a44279bad668af4f7466309b2e6f152a8Steven Thomasconstexpr int kBootFinishedDisplayOffTimeoutSec = 10; 57af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas 58bfe46a053be03836a060853711b467ed5e10affaSteven Thomasconstexpr int kDefaultDisplayWidth = 1920; 59bfe46a053be03836a060853711b467ed5e10affaSteven Thomasconstexpr int kDefaultDisplayHeight = 1080; 60bfe46a053be03836a060853711b467ed5e10affaSteven Thomasconstexpr int64_t kDefaultVsyncPeriodNs = 16666667; 61bfe46a053be03836a060853711b467ed5e10affaSteven Thomas// Hardware composer reports dpi as dots per thousand inches (dpi * 1000). 62bfe46a053be03836a060853711b467ed5e10affaSteven Thomasconstexpr int kDefaultDpi = 400000; 63bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 64a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// Get time offset from a vsync to when the pose for that vsync should be 65a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// predicted out to. For example, if scanout gets halfway through the frame 66a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// at the halfway point between vsyncs, then this could be half the period. 67a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// With global shutter displays, this should be changed to the offset to when 68a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// illumination begins. Low persistence adds a frame of latency, so we predict 69a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// to the center of the next frame. 70a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoinline int64_t GetPosePredictionTimeOffset(int64_t vsync_period_ns) { 71a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko return (vsync_period_ns * 150) / 100; 72a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 73a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// Attempts to set the scheduler class and partiton for the current thread. 752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// Returns true on success or false on failure. 762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakabool SetThreadPolicy(const std::string& scheduler_class, 772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka const std::string& partition) { 782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka int error = dvrSetSchedulerClass(0, scheduler_class.c_str()); 792251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (error < 0) { 802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGE( 812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka "SetThreadPolicy: Failed to set scheduler class \"%s\" for " 822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka "thread_id=%d: %s", 832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka scheduler_class.c_str(), gettid(), strerror(-error)); 842251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka return false; 852251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } 862251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka error = dvrSetCpuPartition(0, partition.c_str()); 872251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (error < 0) { 882251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGE( 892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: " 902251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka "%s", 912251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka partition.c_str(), gettid(), strerror(-error)); 922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka return false; 932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } 942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka return true; 952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka} 962251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 97b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka// Utility to generate scoped tracers with arguments. 98b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka// TODO(eieio): Move/merge this into utils/Trace.h? 99b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabakaclass TraceArgs { 100b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka public: 101b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka template <typename... Args> 102b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka TraceArgs(const char* format, Args&&... args) { 103b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka std::array<char, 1024> buffer; 104b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka snprintf(buffer.data(), buffer.size(), format, std::forward<Args>(args)...); 105b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka atrace_begin(ATRACE_TAG, buffer.data()); 106b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } 107b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 108b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ~TraceArgs() { atrace_end(ATRACE_TAG); } 109b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 110b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka private: 111b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka TraceArgs(const TraceArgs&) = delete; 112b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka void operator=(const TraceArgs&) = delete; 113b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka}; 114b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 115b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka// Macro to define a scoped tracer with arguments. Uses PASTE(x, y) macro 116b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka// defined in utils/Trace.h. 117b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka#define TRACE_FORMAT(format, ...) \ 118b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka TraceArgs PASTE(__tracer, __LINE__) { format, ##__VA_ARGS__ } 119b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 120bfe46a053be03836a060853711b467ed5e10affaSteven Thomas// Returns "primary" or "external". Useful for writing more readable logs. 121bfe46a053be03836a060853711b467ed5e10affaSteven Thomasconst char* GetDisplayName(bool is_primary) { 122bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return is_primary ? "primary" : "external"; 123bfe46a053be03836a060853711b467ed5e10affaSteven Thomas} 124bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 125a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} // anonymous namespace 126a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 127a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex VakulenkoHardwareComposer::HardwareComposer() 128b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas : initialized_(false), request_display_callback_(nullptr) {} 129a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 130a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex VakulenkoHardwareComposer::~HardwareComposer(void) { 1312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka UpdatePostThreadState(PostThreadState::Quit, true); 1322251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (post_thread_.joinable()) 133050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas post_thread_.join(); 134a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 135a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 136b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomasbool HardwareComposer::Initialize( 1376e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas Hwc2::Composer* composer, hwc2_display_t primary_display_id, 1386e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas RequestDisplayCallback request_display_callback) { 139016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk if (initialized_) { 140016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk ALOGE("HardwareComposer::Initialize: already initialized."); 141a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko return false; 142a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 143a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 144451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka is_standalone_device_ = property_get_bool(kDvrStandaloneProperty, false); 145451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka 146b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas request_display_callback_ = request_display_callback; 147b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas 148bfe46a053be03836a060853711b467ed5e10affaSteven Thomas primary_display_ = GetDisplayParams(composer, primary_display_id, true); 1492c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 1502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); 151050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas LOG_ALWAYS_FATAL_IF( 1522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka !post_thread_event_fd_, 153050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas "HardwareComposer: Failed to create interrupt event fd : %s", 154050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas strerror(errno)); 155050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas 156050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas post_thread_ = std::thread(&HardwareComposer::PostThread, this); 157050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas 158016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk initialized_ = true; 159016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk 160016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk return initialized_; 161016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk} 162016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk 163050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasvoid HardwareComposer::Enable() { 1642251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka UpdatePostThreadState(PostThreadState::Suspended, false); 165050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas} 1667480c060cb3466d97ec3125d61bbace153f534c8Jin Qian 167050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasvoid HardwareComposer::Disable() { 1682251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka UpdatePostThreadState(PostThreadState::Suspended, true); 1697f8761eef7d657a4f341f3792ff887638940cc47Steven Thomas 1707f8761eef7d657a4f341f3792ff887638940cc47Steven Thomas std::unique_lock<std::mutex> lock(post_thread_mutex_); 1717f8761eef7d657a4f341f3792ff887638940cc47Steven Thomas post_thread_ready_.wait(lock, [this] { 1727f8761eef7d657a4f341f3792ff887638940cc47Steven Thomas return !post_thread_resumed_; 1737f8761eef7d657a4f341f3792ff887638940cc47Steven Thomas }); 1742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka} 1752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 176af33627a44279bad668af4f7466309b2e6f152a8Steven Thomasvoid HardwareComposer::OnBootFinished() { 177af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas std::lock_guard<std::mutex> lock(post_thread_mutex_); 178af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas if (boot_finished_) 179af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas return; 180af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas boot_finished_ = true; 181af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas post_thread_wait_.notify_one(); 182af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas if (is_standalone_device_) 183af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas request_display_callback_(true); 184af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas} 185af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas 1862251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// Update the post thread quiescent state based on idle and suspended inputs. 1872251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid HardwareComposer::UpdatePostThreadState(PostThreadStateType state, 1882251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka bool suspend) { 189050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas std::unique_lock<std::mutex> lock(post_thread_mutex_); 1902251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 1912251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // Update the votes in the state variable before evaluating the effective 1922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // quiescent state. Any bits set in post_thread_state_ indicate that the post 1932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // thread should be suspended. 1942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (suspend) { 1952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_state_ |= state; 1962251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } else { 1972251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_state_ &= ~state; 1982251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } 1992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 2002251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka const bool quit = post_thread_state_ & PostThreadState::Quit; 2012251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka const bool effective_suspend = post_thread_state_ != PostThreadState::Active; 2022251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (quit) { 2032251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_quiescent_ = true; 2042251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka eventfd_write(post_thread_event_fd_.Get(), 1); 2052251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_wait_.notify_one(); 2062251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } else if (effective_suspend && !post_thread_quiescent_) { 2072251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_quiescent_ = true; 2082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka eventfd_write(post_thread_event_fd_.Get(), 1); 2092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } else if (!effective_suspend && post_thread_quiescent_) { 2102251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_quiescent_ = false; 2112251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka eventfd_t value; 2122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka eventfd_read(post_thread_event_fd_.Get(), &value); 2132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_wait_.notify_one(); 214050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas } 215050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas} 216a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 217bfe46a053be03836a060853711b467ed5e10affaSteven Thomasvoid HardwareComposer::CreateComposer() { 218bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (composer_) 219bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return; 220bfe46a053be03836a060853711b467ed5e10affaSteven Thomas composer_.reset(new Hwc2::impl::Composer("default")); 221bfe46a053be03836a060853711b467ed5e10affaSteven Thomas composer_callback_ = new ComposerCallback; 222bfe46a053be03836a060853711b467ed5e10affaSteven Thomas composer_->registerCallback(composer_callback_); 223bfe46a053be03836a060853711b467ed5e10affaSteven Thomas LOG_ALWAYS_FATAL_IF(!composer_callback_->GotFirstHotplug(), 224bfe46a053be03836a060853711b467ed5e10affaSteven Thomas "Registered composer callback but didn't get hotplug for primary" 225bfe46a053be03836a060853711b467ed5e10affaSteven Thomas " display"); 226bfe46a053be03836a060853711b467ed5e10affaSteven Thomas} 2270af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas 228bfe46a053be03836a060853711b467ed5e10affaSteven Thomasvoid HardwareComposer::OnPostThreadResumed() { 229bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI("OnPostThreadResumed"); 230bfe46a053be03836a060853711b467ed5e10affaSteven Thomas EnableDisplay(*target_display_, true); 231a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 232050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas // Trigger target-specific performance mode change. 233050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas property_set(kDvrPerformanceProperty, "performance"); 234a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 235a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 236050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasvoid HardwareComposer::OnPostThreadPaused() { 237bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI("OnPostThreadPaused"); 238a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko retire_fence_fds_.clear(); 2392c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layers_.clear(); 240a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 241bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // Phones create a new composer client on resume and destroy it on pause. 242bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // Standalones only create the composer client once and then use SetPowerMode 243bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // to control the screen on pause/resume. 244451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka if (!is_standalone_device_) { 245451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka composer_callback_ = nullptr; 246451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka composer_.reset(nullptr); 247451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka } else { 248bfe46a053be03836a060853711b467ed5e10affaSteven Thomas EnableDisplay(*target_display_, false); 249451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka } 2500af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas 251050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas // Trigger target-specific performance mode change. 252050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas property_set(kDvrPerformanceProperty, "idle"); 253a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 254a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 255af33627a44279bad668af4f7466309b2e6f152a8Steven Thomasbool HardwareComposer::PostThreadCondWait(std::unique_lock<std::mutex>& lock, 256af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas int timeout_sec, 257af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas const std::function<bool()>& pred) { 258af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas auto pred_with_quit = [&] { 259af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas return pred() || (post_thread_state_ & PostThreadState::Quit); 260af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas }; 261af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas if (timeout_sec >= 0) { 262af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas post_thread_wait_.wait_for(lock, std::chrono::seconds(timeout_sec), 263af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas pred_with_quit); 264af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas } else { 265af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas post_thread_wait_.wait(lock, pred_with_quit); 266af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas } 267af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas if (post_thread_state_ & PostThreadState::Quit) { 268af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas ALOGI("HardwareComposer::PostThread: Quitting."); 269af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas return true; 270af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas } 271af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas return false; 272af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas} 273af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas 2742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaHWC::Error HardwareComposer::Validate(hwc2_display_t display) { 275a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko uint32_t num_types; 276a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko uint32_t num_requests; 2772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka HWC::Error error = 2782c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka composer_->validateDisplay(display, &num_types, &num_requests); 279a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 280a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko if (error == HWC2_ERROR_HAS_CHANGES) { 281bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGE("Hardware composer has requested composition changes, " 282bfe46a053be03836a060853711b467ed5e10affaSteven Thomas "which we don't support."); 283bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // Accept the changes anyway and see if we can get something on the screen. 2842c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka error = composer_->acceptDisplayChanges(display); 285a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 286a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 287a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko return error; 288a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 289a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 290bfe46a053be03836a060853711b467ed5e10affaSteven Thomasbool HardwareComposer::EnableVsync(const DisplayParams& display, bool enabled) { 291bfe46a053be03836a060853711b467ed5e10affaSteven Thomas HWC::Error error = composer_->setVsyncEnabled(display.id, 292a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE 293a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko : HWC2_VSYNC_DISABLE)); 294bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (error != HWC::Error::None) { 295bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGE("Error attempting to %s vsync on %s display: %s", 296bfe46a053be03836a060853711b467ed5e10affaSteven Thomas enabled ? "enable" : "disable", GetDisplayName(display.is_primary), 297bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error.to_string().c_str()); 298bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 299bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return error == HWC::Error::None; 300a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 301a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 302bfe46a053be03836a060853711b467ed5e10affaSteven Thomasbool HardwareComposer::SetPowerMode(const DisplayParams& display, bool active) { 303bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI("Turning %s display %s", GetDisplayName(display.is_primary), 304bfe46a053be03836a060853711b467ed5e10affaSteven Thomas active ? "on" : "off"); 305451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off; 306bfe46a053be03836a060853711b467ed5e10affaSteven Thomas HWC::Error error = composer_->setPowerMode(display.id, 3076e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas power_mode.cast<Hwc2::IComposerClient::PowerMode>()); 308bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (error != HWC::Error::None) { 309bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGE("Error attempting to turn %s display %s: %s", 310bfe46a053be03836a060853711b467ed5e10affaSteven Thomas GetDisplayName(display.is_primary), active ? "on" : "off", 311bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error.to_string().c_str()); 312bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 313bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return error == HWC::Error::None; 314bfe46a053be03836a060853711b467ed5e10affaSteven Thomas} 315bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 316bfe46a053be03836a060853711b467ed5e10affaSteven Thomasbool HardwareComposer::EnableDisplay(const DisplayParams& display, 317bfe46a053be03836a060853711b467ed5e10affaSteven Thomas bool enabled) { 318bfe46a053be03836a060853711b467ed5e10affaSteven Thomas bool power_result; 319bfe46a053be03836a060853711b467ed5e10affaSteven Thomas bool vsync_result; 320bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // When turning a display on, we set the power state then set vsync. When 321bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // turning a display off we do it in the opposite order. 322bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (enabled) { 323bfe46a053be03836a060853711b467ed5e10affaSteven Thomas power_result = SetPowerMode(display, enabled); 324bfe46a053be03836a060853711b467ed5e10affaSteven Thomas vsync_result = EnableVsync(display, enabled); 325bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } else { 326bfe46a053be03836a060853711b467ed5e10affaSteven Thomas vsync_result = EnableVsync(display, enabled); 327bfe46a053be03836a060853711b467ed5e10affaSteven Thomas power_result = SetPowerMode(display, enabled); 328bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 329bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return power_result && vsync_result; 330451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka} 331451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka 3322251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaHWC::Error HardwareComposer::Present(hwc2_display_t display) { 333a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko int32_t present_fence; 3342c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka HWC::Error error = composer_->presentDisplay(display, &present_fence); 335a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 336a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // According to the documentation, this fence is signaled at the time of 337a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // vsync/DMA for physical displays. 3382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (error == HWC::Error::None) { 339a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ATRACE_INT("HardwareComposer: VsyncFence", present_fence); 340a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko retire_fence_fds_.emplace_back(present_fence); 341a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } else { 342a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ATRACE_INT("HardwareComposer: PresentResult", error); 343a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 344a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 345a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko return error; 346a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 347a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 348bfe46a053be03836a060853711b467ed5e10affaSteven ThomasDisplayParams HardwareComposer::GetDisplayParams( 349bfe46a053be03836a060853711b467ed5e10affaSteven Thomas Hwc2::Composer* composer, hwc2_display_t display, bool is_primary) { 350bfe46a053be03836a060853711b467ed5e10affaSteven Thomas DisplayParams params; 351bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.id = display; 352bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.is_primary = is_primary; 353a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 354bfe46a053be03836a060853711b467ed5e10affaSteven Thomas Hwc2::Config config; 355bfe46a053be03836a060853711b467ed5e10affaSteven Thomas HWC::Error error = composer->getActiveConfig(display, &config); 356a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 357bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (error == HWC::Error::None) { 358bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto get_attr = [&](hwc2_attribute_t attr, const char* attr_name) 359bfe46a053be03836a060853711b467ed5e10affaSteven Thomas -> std::optional<int32_t> { 360bfe46a053be03836a060853711b467ed5e10affaSteven Thomas int32_t val; 361bfe46a053be03836a060853711b467ed5e10affaSteven Thomas HWC::Error error = composer->getDisplayAttribute( 362bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display, config, (Hwc2::IComposerClient::Attribute)attr, &val); 363bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (error != HWC::Error::None) { 364bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGE("Failed to get %s display attr %s: %s", 365bfe46a053be03836a060853711b467ed5e10affaSteven Thomas GetDisplayName(is_primary), attr_name, 366bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error.to_string().c_str()); 367bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return std::nullopt; 368bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 369bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return val; 370bfe46a053be03836a060853711b467ed5e10affaSteven Thomas }; 371a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 372bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto width = get_attr(HWC2_ATTRIBUTE_WIDTH, "width"); 373bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto height = get_attr(HWC2_ATTRIBUTE_HEIGHT, "height"); 374a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 375bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (width && height) { 376bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.width = *width; 377bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.height = *height; 378bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } else { 379bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI("Failed to get width and/or height for %s display. Using default" 380bfe46a053be03836a060853711b467ed5e10affaSteven Thomas " size %dx%d.", GetDisplayName(is_primary), kDefaultDisplayWidth, 381bfe46a053be03836a060853711b467ed5e10affaSteven Thomas kDefaultDisplayHeight); 382bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.width = kDefaultDisplayWidth; 383bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.height = kDefaultDisplayHeight; 384bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 385a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 386bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto vsync_period = get_attr(HWC2_ATTRIBUTE_VSYNC_PERIOD, "vsync period"); 387bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (vsync_period) { 388bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.vsync_period_ns = *vsync_period; 389bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } else { 390bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI("Failed to get vsync period for %s display. Using default vsync" 391bfe46a053be03836a060853711b467ed5e10affaSteven Thomas " period %.2fms", GetDisplayName(is_primary), 392bfe46a053be03836a060853711b467ed5e10affaSteven Thomas static_cast<float>(kDefaultVsyncPeriodNs) / 1000000); 393bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.vsync_period_ns = kDefaultVsyncPeriodNs; 394bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 395a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 396bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto dpi_x = get_attr(HWC2_ATTRIBUTE_DPI_X, "DPI X"); 397bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto dpi_y = get_attr(HWC2_ATTRIBUTE_DPI_Y, "DPI Y"); 398bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (dpi_x && dpi_y) { 399bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.dpi.x = *dpi_x; 400bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.dpi.y = *dpi_y; 401bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } else { 402bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI("Failed to get dpi_x and/or dpi_y for %s display. Using default" 403bfe46a053be03836a060853711b467ed5e10affaSteven Thomas " dpi %d.", GetDisplayName(is_primary), kDefaultDpi); 404bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.dpi.x = kDefaultDpi; 405bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.dpi.y = kDefaultDpi; 406bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 407bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } else { 408bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGE("HardwareComposer: Failed to get current %s display config: %d." 409bfe46a053be03836a060853711b467ed5e10affaSteven Thomas " Using default display values.", 410bfe46a053be03836a060853711b467ed5e10affaSteven Thomas GetDisplayName(is_primary), error.value); 411bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.width = kDefaultDisplayWidth; 412bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.height = kDefaultDisplayHeight; 413bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.dpi.x = kDefaultDpi; 414bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.dpi.y = kDefaultDpi; 415bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.vsync_period_ns = kDefaultVsyncPeriodNs; 416a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 417a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 418bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI( 419bfe46a053be03836a060853711b467ed5e10affaSteven Thomas "HardwareComposer: %s display attributes: width=%d height=%d " 420bfe46a053be03836a060853711b467ed5e10affaSteven Thomas "vsync_period_ns=%d DPI=%dx%d", 421bfe46a053be03836a060853711b467ed5e10affaSteven Thomas GetDisplayName(is_primary), 422bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.width, 423bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.height, 424bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.vsync_period_ns, 425bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.dpi.x, 426bfe46a053be03836a060853711b467ed5e10affaSteven Thomas params.dpi.y); 427bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 428bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return params; 429a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 430a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 4310b485c91f95fa7022998971fb9f407fe198bb853Corey Tabakastd::string HardwareComposer::Dump() { 4320b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka std::unique_lock<std::mutex> lock(post_thread_mutex_); 4330b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka std::ostringstream stream; 4340b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka 435bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto print_display_metrics = [&](const DisplayParams& params) { 436bfe46a053be03836a060853711b467ed5e10affaSteven Thomas stream << GetDisplayName(params.is_primary) 437bfe46a053be03836a060853711b467ed5e10affaSteven Thomas << " display metrics: " << params.width << "x" 438bfe46a053be03836a060853711b467ed5e10affaSteven Thomas << params.height << " " << (params.dpi.x / 1000.0) 439bfe46a053be03836a060853711b467ed5e10affaSteven Thomas << "x" << (params.dpi.y / 1000.0) << " dpi @ " 440bfe46a053be03836a060853711b467ed5e10affaSteven Thomas << (1000000000.0 / params.vsync_period_ns) << " Hz" 441bfe46a053be03836a060853711b467ed5e10affaSteven Thomas << std::endl; 442bfe46a053be03836a060853711b467ed5e10affaSteven Thomas }; 443bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 444bfe46a053be03836a060853711b467ed5e10affaSteven Thomas print_display_metrics(primary_display_); 445bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (external_display_) 446bfe46a053be03836a060853711b467ed5e10affaSteven Thomas print_display_metrics(*external_display_); 4470b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka 4480b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka stream << "Post thread resumed: " << post_thread_resumed_ << std::endl; 4492c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka stream << "Active layers: " << layers_.size() << std::endl; 4500b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka stream << std::endl; 4510b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka 4522c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka for (size_t i = 0; i < layers_.size(); i++) { 4530b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka stream << "Layer " << i << ":"; 4540b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka stream << " type=" << layers_[i].GetCompositionType().to_string(); 4550b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka stream << " surface_id=" << layers_[i].GetSurfaceId(); 4560b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka stream << " buffer_id=" << layers_[i].GetBufferId(); 4570b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka stream << std::endl; 4580b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka } 4590b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka stream << std::endl; 4600b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka 4610b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka if (post_thread_resumed_) { 4620b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka stream << "Hardware Composer Debug Info:" << std::endl; 4632c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka stream << composer_->dumpDebugInfo(); 4640b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka } 4650b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka 4660b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka return stream.str(); 4670b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka} 468a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 469bfe46a053be03836a060853711b467ed5e10affaSteven Thomasvoid HardwareComposer::PostLayers(hwc2_display_t display) { 470a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ATRACE_NAME("HardwareComposer::PostLayers"); 471a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 472a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // Setup the hardware composer layers with current buffers. 4732c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka for (auto& layer : layers_) { 4742c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layer.Prepare(); 475a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 476a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 477a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // Now that we have taken in a frame from the application, we have a chance 478a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // to drop the frame before passing the frame along to HWC. 479a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // If the display driver has become backed up, we detect it here and then 480a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // react by skipping this frame to catch up latency. 481a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko while (!retire_fence_fds_.empty() && 482a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko (!retire_fence_fds_.front() || 483a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) { 484a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // There are only 2 fences in here, no performance problem to shift the 485a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // array of ints. 486a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko retire_fence_fds_.erase(retire_fence_fds_.begin()); 487a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 488a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 489353a6f69f2ff24c4f10d4994afaa1d4d46bcb9a6George Burgess IV const bool is_fence_pending = static_cast<int32_t>(retire_fence_fds_.size()) > 490954796e27e89209b38b35779949c243bec490c28John Bates post_thread_config_.allowed_pending_fence_count; 491a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 492b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka if (is_fence_pending) { 493a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ATRACE_INT("frame_skip_count", ++frame_skip_count_); 494a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 495a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ALOGW_IF(is_fence_pending, 496a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko "Warning: dropping a frame to catch up with HWC (pending = %zd)", 497a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko retire_fence_fds_.size()); 498a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 4992c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka for (auto& layer : layers_) { 5002c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layer.Drop(); 501a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 502a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko return; 503a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } else { 504a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // Make the transition more obvious in systrace when the frame skip happens 505a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // above. 506a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ATRACE_INT("frame_skip_count", 0); 507a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 508a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 50989bbefcb31d77059c275abe843578d09264475c9Corey Tabaka#if TRACE > 1 5102c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka for (size_t i = 0; i < layers_.size(); i++) { 5110b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka ALOGI("HardwareComposer::PostLayers: layer=%zu buffer_id=%d composition=%s", 5120b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka i, layers_[i].GetBufferId(), 5132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka layers_[i].GetCompositionType().to_string().c_str()); 5140b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka } 515a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#endif 516a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 517bfe46a053be03836a060853711b467ed5e10affaSteven Thomas HWC::Error error = Validate(display); 5184668484104f28a30ada7c6906f05c818e82f9bf4John Bates if (error != HWC::Error::None) { 519bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGE("HardwareComposer::PostLayers: Validate failed: %s display=%" PRIu64, 520bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error.to_string().c_str(), display); 5214668484104f28a30ada7c6906f05c818e82f9bf4John Bates return; 5224668484104f28a30ada7c6906f05c818e82f9bf4John Bates } 5234668484104f28a30ada7c6906f05c818e82f9bf4John Bates 524bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error = Present(display); 5252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (error != HWC::Error::None) { 5262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGE("HardwareComposer::PostLayers: Present failed: %s", 5272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka error.to_string().c_str()); 528a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko return; 529a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 530a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 531a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko std::vector<Hwc2::Layer> out_layers; 532a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko std::vector<int> out_fences; 533bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error = composer_->getReleaseFences(display, 5346e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas &out_layers, &out_fences); 5352251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGE_IF(error != HWC::Error::None, 5362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka "HardwareComposer::PostLayers: Failed to get release fences: %s", 5372251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka error.to_string().c_str()); 538a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 5392c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // Perform post-frame bookkeeping. 5402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka uint32_t num_elements = out_layers.size(); 541a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko for (size_t i = 0; i < num_elements; ++i) { 5422c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka for (auto& layer : layers_) { 5432c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka if (layer.GetLayerHandle() == out_layers[i]) { 5442c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layer.Finish(out_fences[i]); 545a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 546a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 547a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 548a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 549a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 550050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasvoid HardwareComposer::SetDisplaySurfaces( 5512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) { 552a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd", 553a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko surfaces.size()); 5542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka const bool display_idle = surfaces.size() == 0; 5552251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka { 5562251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka std::unique_lock<std::mutex> lock(post_thread_mutex_); 557bfe46a053be03836a060853711b467ed5e10affaSteven Thomas surfaces_ = std::move(surfaces); 558bfe46a053be03836a060853711b467ed5e10affaSteven Thomas surfaces_changed_ = true; 5592251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } 5602251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 561af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas if (request_display_callback_ && !is_standalone_device_) 5622ddf567064b5c307bec097293e40ac4eeb8f4b49Steven Thomas request_display_callback_(!display_idle); 5632ddf567064b5c307bec097293e40ac4eeb8f4b49Steven Thomas 5642251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // Set idle state based on whether there are any surfaces to handle. 5652251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka UpdatePostThreadState(PostThreadState::Idle, display_idle); 566050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas} 567a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 568954796e27e89209b38b35779949c243bec490c28John Batesint HardwareComposer::OnNewGlobalBuffer(DvrGlobalBufferKey key, 569954796e27e89209b38b35779949c243bec490c28John Bates IonBuffer& ion_buffer) { 570822b710a714c342dda0087f594c8ababa6630f44Okan Arikan if (key == DvrGlobalBuffers::kVsyncBuffer) { 571822b710a714c342dda0087f594c8ababa6630f44Okan Arikan vsync_ring_ = std::make_unique<CPUMappedBroadcastRing<DvrVsyncRing>>( 572822b710a714c342dda0087f594c8ababa6630f44Okan Arikan &ion_buffer, CPUUsageMode::WRITE_OFTEN); 573822b710a714c342dda0087f594c8ababa6630f44Okan Arikan 574822b710a714c342dda0087f594c8ababa6630f44Okan Arikan if (vsync_ring_->IsMapped() == false) { 575822b710a714c342dda0087f594c8ababa6630f44Okan Arikan return -EPERM; 576822b710a714c342dda0087f594c8ababa6630f44Okan Arikan } 577822b710a714c342dda0087f594c8ababa6630f44Okan Arikan } 578822b710a714c342dda0087f594c8ababa6630f44Okan Arikan 579822b710a714c342dda0087f594c8ababa6630f44Okan Arikan if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) { 580954796e27e89209b38b35779949c243bec490c28John Bates return MapConfigBuffer(ion_buffer); 581954796e27e89209b38b35779949c243bec490c28John Bates } 582954796e27e89209b38b35779949c243bec490c28John Bates 583954796e27e89209b38b35779949c243bec490c28John Bates return 0; 584954796e27e89209b38b35779949c243bec490c28John Bates} 585954796e27e89209b38b35779949c243bec490c28John Bates 586954796e27e89209b38b35779949c243bec490c28John Batesvoid HardwareComposer::OnDeletedGlobalBuffer(DvrGlobalBufferKey key) { 587822b710a714c342dda0087f594c8ababa6630f44Okan Arikan if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) { 588954796e27e89209b38b35779949c243bec490c28John Bates ConfigBufferDeleted(); 589954796e27e89209b38b35779949c243bec490c28John Bates } 590954796e27e89209b38b35779949c243bec490c28John Bates} 591954796e27e89209b38b35779949c243bec490c28John Bates 592954796e27e89209b38b35779949c243bec490c28John Batesint HardwareComposer::MapConfigBuffer(IonBuffer& ion_buffer) { 593954796e27e89209b38b35779949c243bec490c28John Bates std::lock_guard<std::mutex> lock(shared_config_mutex_); 5946f468c6a3731d2bae41c4b86143b7246fcde1f83Okan Arikan shared_config_ring_ = DvrConfigRing(); 595954796e27e89209b38b35779949c243bec490c28John Bates 5966f468c6a3731d2bae41c4b86143b7246fcde1f83Okan Arikan if (ion_buffer.width() < DvrConfigRing::MemorySize()) { 597954796e27e89209b38b35779949c243bec490c28John Bates ALOGE("HardwareComposer::MapConfigBuffer: invalid buffer size."); 598954796e27e89209b38b35779949c243bec490c28John Bates return -EINVAL; 599954796e27e89209b38b35779949c243bec490c28John Bates } 600954796e27e89209b38b35779949c243bec490c28John Bates 601954796e27e89209b38b35779949c243bec490c28John Bates void* buffer_base = 0; 602954796e27e89209b38b35779949c243bec490c28John Bates int result = ion_buffer.Lock(ion_buffer.usage(), 0, 0, ion_buffer.width(), 603954796e27e89209b38b35779949c243bec490c28John Bates ion_buffer.height(), &buffer_base); 604954796e27e89209b38b35779949c243bec490c28John Bates if (result != 0) { 6050b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka ALOGE( 6060b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka "HardwareComposer::MapConfigBuffer: Failed to map vrflinger config " 6070b485c91f95fa7022998971fb9f407fe198bb853Corey Tabaka "buffer."); 608954796e27e89209b38b35779949c243bec490c28John Bates return -EPERM; 609954796e27e89209b38b35779949c243bec490c28John Bates } 610954796e27e89209b38b35779949c243bec490c28John Bates 6116f468c6a3731d2bae41c4b86143b7246fcde1f83Okan Arikan shared_config_ring_ = DvrConfigRing::Create(buffer_base, ion_buffer.width()); 612954796e27e89209b38b35779949c243bec490c28John Bates ion_buffer.Unlock(); 613954796e27e89209b38b35779949c243bec490c28John Bates 614954796e27e89209b38b35779949c243bec490c28John Bates return 0; 615954796e27e89209b38b35779949c243bec490c28John Bates} 616954796e27e89209b38b35779949c243bec490c28John Bates 617954796e27e89209b38b35779949c243bec490c28John Batesvoid HardwareComposer::ConfigBufferDeleted() { 618954796e27e89209b38b35779949c243bec490c28John Bates std::lock_guard<std::mutex> lock(shared_config_mutex_); 6196f468c6a3731d2bae41c4b86143b7246fcde1f83Okan Arikan shared_config_ring_ = DvrConfigRing(); 620954796e27e89209b38b35779949c243bec490c28John Bates} 621954796e27e89209b38b35779949c243bec490c28John Bates 622954796e27e89209b38b35779949c243bec490c28John Batesvoid HardwareComposer::UpdateConfigBuffer() { 623954796e27e89209b38b35779949c243bec490c28John Bates std::lock_guard<std::mutex> lock(shared_config_mutex_); 624954796e27e89209b38b35779949c243bec490c28John Bates if (!shared_config_ring_.is_valid()) 625954796e27e89209b38b35779949c243bec490c28John Bates return; 626954796e27e89209b38b35779949c243bec490c28John Bates // Copy from latest record in shared_config_ring_ to local copy. 6276f468c6a3731d2bae41c4b86143b7246fcde1f83Okan Arikan DvrConfig record; 628954796e27e89209b38b35779949c243bec490c28John Bates if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) { 629cc65c3c6c748a5bb87395a9233d01358ef638f4bJohn Bates ALOGI("DvrConfig updated: sequence %u, post offset %d", 630cc65c3c6c748a5bb87395a9233d01358ef638f4bJohn Bates shared_config_ring_sequence_, record.frame_post_offset_ns); 631cc65c3c6c748a5bb87395a9233d01358ef638f4bJohn Bates ++shared_config_ring_sequence_; 632954796e27e89209b38b35779949c243bec490c28John Bates post_thread_config_ = record; 633954796e27e89209b38b35779949c243bec490c28John Bates } 634954796e27e89209b38b35779949c243bec490c28John Bates} 635954796e27e89209b38b35779949c243bec490c28John Bates 6362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakaint HardwareComposer::PostThreadPollInterruptible( 637b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) { 638050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas pollfd pfd[2] = { 639050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas { 6402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka .fd = event_fd.Get(), 64166747c180e456cc762821c61a75a17bee03a4cf9Steven Thomas .events = static_cast<short>(requested_events), 64266747c180e456cc762821c61a75a17bee03a4cf9Steven Thomas .revents = 0, 643050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas }, 644050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas { 6452251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka .fd = post_thread_event_fd_.Get(), 646050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas .events = POLLPRI | POLLIN, 647050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas .revents = 0, 648050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas }, 649050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas }; 650050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas int ret, error; 651050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas do { 652b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas ret = poll(pfd, 2, timeout_ms); 653050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas error = errno; 654050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas ALOGW_IF(ret < 0, 655050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas "HardwareComposer::PostThreadPollInterruptible: Error during " 656050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas "poll(): %s (%d)", 657050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas strerror(error), error); 658050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas } while (ret < 0 && error == EINTR); 6597480c060cb3466d97ec3125d61bbace153f534c8Jin Qian 660050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas if (ret < 0) { 661050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas return -error; 662b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas } else if (ret == 0) { 663b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas return -ETIMEDOUT; 664050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas } else if (pfd[0].revents != 0) { 665050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas return 0; 666050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas } else if (pfd[1].revents != 0) { 6670d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka ALOGI("VrHwcPost thread interrupted: revents=%x", pfd[1].revents); 668050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas return kPostThreadInterrupted; 669050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas } else { 670050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas return 0; 6717480c060cb3466d97ec3125d61bbace153f534c8Jin Qian } 672a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 673a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 674bfe46a053be03836a060853711b467ed5e10affaSteven Thomas// Sleep until the next predicted vsync, returning the predicted vsync 675bfe46a053be03836a060853711b467ed5e10affaSteven Thomas// timestamp. 676bfe46a053be03836a060853711b467ed5e10affaSteven ThomasStatus<int64_t> HardwareComposer::WaitForPredictedVSync() { 677bfe46a053be03836a060853711b467ed5e10affaSteven Thomas const int64_t predicted_vsync_time = last_vsync_timestamp_ + 678bfe46a053be03836a060853711b467ed5e10affaSteven Thomas (target_display_->vsync_period_ns * vsync_prediction_interval_); 679b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka const int error = SleepUntil(predicted_vsync_time); 680b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka if (error < 0) { 681b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ALOGE("HardwareComposer::WaifForVSync:: Failed to sleep: %s", 682b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka strerror(-error)); 683b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas return error; 684a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 685b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka return {predicted_vsync_time}; 686a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 687a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 688a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoint HardwareComposer::SleepUntil(int64_t wakeup_timestamp) { 689a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko const int timer_fd = vsync_sleep_timer_fd_.Get(); 690a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko const itimerspec wakeup_itimerspec = { 691a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko .it_interval = {.tv_sec = 0, .tv_nsec = 0}, 692a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko .it_value = NsToTimespec(wakeup_timestamp), 693a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko }; 694a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko int ret = 695a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr); 696a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko int error = errno; 697a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko if (ret < 0) { 698a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s", 699a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko strerror(error)); 700a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko return -error; 701a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 702a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 703451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN, 704451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka /*timeout_ms*/ -1); 705a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 706a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 707a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid HardwareComposer::PostThread() { 708a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // NOLINTNEXTLINE(runtime/int) 709050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0); 710a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 7112251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // Set the scheduler to SCHED_FIFO with high priority. If this fails here 7122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // there may have been a startup timing issue between this thread and 7132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // performanced. Try again later when this thread becomes active. 7142251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka bool thread_policy_setup = 7152251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka SetThreadPolicy("graphics:high", "/system/performance"); 716a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 717050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas // Create a timerfd based on CLOCK_MONOTINIC. 718050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0)); 719050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas LOG_ALWAYS_FATAL_IF( 720050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas !vsync_sleep_timer_fd_, 721050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas "HardwareComposer: Failed to create vsync sleep timerfd: %s", 722050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas strerror(errno)); 723a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 724bfe46a053be03836a060853711b467ed5e10affaSteven Thomas struct VsyncEyeOffsets { int64_t left_ns, right_ns; }; 725bfe46a053be03836a060853711b467ed5e10affaSteven Thomas bool was_running = false; 726a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 727bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto get_vsync_eye_offsets = [this]() -> VsyncEyeOffsets { 728bfe46a053be03836a060853711b467ed5e10affaSteven Thomas VsyncEyeOffsets offsets; 729bfe46a053be03836a060853711b467ed5e10affaSteven Thomas offsets.left_ns = 730bfe46a053be03836a060853711b467ed5e10affaSteven Thomas GetPosePredictionTimeOffset(target_display_->vsync_period_ns); 731a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 732bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // TODO(jbates) Query vblank time from device, when such an API is 733bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // available. This value (6.3%) was measured on A00 in low persistence mode. 734bfe46a053be03836a060853711b467ed5e10affaSteven Thomas int64_t vblank_ns = target_display_->vsync_period_ns * 63 / 1000; 735bfe46a053be03836a060853711b467ed5e10affaSteven Thomas offsets.right_ns = (target_display_->vsync_period_ns - vblank_ns) / 2; 736a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 737bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // Check property for overriding right eye offset value. 738bfe46a053be03836a060853711b467ed5e10affaSteven Thomas offsets.right_ns = 739bfe46a053be03836a060853711b467ed5e10affaSteven Thomas property_get_int64(kRightEyeOffsetProperty, offsets.right_ns); 740bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 741bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return offsets; 742bfe46a053be03836a060853711b467ed5e10affaSteven Thomas }; 743bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 744bfe46a053be03836a060853711b467ed5e10affaSteven Thomas VsyncEyeOffsets vsync_eye_offsets = get_vsync_eye_offsets(); 745050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas 746af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas if (is_standalone_device_) { 747af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas // First, wait until boot finishes. 748af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas std::unique_lock<std::mutex> lock(post_thread_mutex_); 749af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas if (PostThreadCondWait(lock, -1, [this] { return boot_finished_; })) { 750af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas return; 751af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas } 752af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas 753af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas // Then, wait until we're either leaving the quiescent state, or the boot 754af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas // finished display off timeout expires. 755af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas if (PostThreadCondWait(lock, kBootFinishedDisplayOffTimeoutSec, 756af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas [this] { return !post_thread_quiescent_; })) { 757af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas return; 758af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas } 759af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas 760af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas LOG_ALWAYS_FATAL_IF(post_thread_state_ & PostThreadState::Suspended, 761af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas "Vr flinger should own the display by now."); 762af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas post_thread_resumed_ = true; 763af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas post_thread_ready_.notify_all(); 764bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (!composer_) 765bfe46a053be03836a060853711b467ed5e10affaSteven Thomas CreateComposer(); 766af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas } 767af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas 768a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko while (1) { 769a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ATRACE_NAME("HardwareComposer::PostThread"); 770a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 771954796e27e89209b38b35779949c243bec490c28John Bates // Check for updated config once per vsync. 772954796e27e89209b38b35779949c243bec490c28John Bates UpdateConfigBuffer(); 773954796e27e89209b38b35779949c243bec490c28John Bates 7742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka while (post_thread_quiescent_) { 775050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas std::unique_lock<std::mutex> lock(post_thread_mutex_); 7762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGI("HardwareComposer::PostThread: Entering quiescent state."); 7772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 778bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // Tear down resources. 779bfe46a053be03836a060853711b467ed5e10affaSteven Thomas OnPostThreadPaused(); 7802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka was_running = false; 7812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_resumed_ = false; 7822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_ready_.notify_all(); 7832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 784af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas if (PostThreadCondWait(lock, -1, 785af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas [this] { return !post_thread_quiescent_; })) { 786af33627a44279bad668af4f7466309b2e6f152a8Steven Thomas // A true return value means we've been asked to quit. 7872251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka return; 788282a5ed48f64e4010f97ca4077e3bd4b54ba3268Steven Thomas } 7892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 7902251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_resumed_ = true; 7912251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka post_thread_ready_.notify_all(); 7922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 7932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGI("HardwareComposer::PostThread: Exiting quiescent state."); 794050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas } 795050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas 796bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (!composer_) 797bfe46a053be03836a060853711b467ed5e10affaSteven Thomas CreateComposer(); 798bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 799bfe46a053be03836a060853711b467ed5e10affaSteven Thomas bool target_display_changed = UpdateTargetDisplay(); 800bfe46a053be03836a060853711b467ed5e10affaSteven Thomas bool just_resumed_running = !was_running; 801bfe46a053be03836a060853711b467ed5e10affaSteven Thomas was_running = true; 802bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 803bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (target_display_changed) 804bfe46a053be03836a060853711b467ed5e10affaSteven Thomas vsync_eye_offsets = get_vsync_eye_offsets(); 805bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 806bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (just_resumed_running) { 807050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas OnPostThreadResumed(); 8082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 8092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // Try to setup the scheduler policy if it failed during startup. Only 8102251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // attempt to do this on transitions from inactive to active to avoid 8112251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // spamming the system with RPCs and log messages. 8122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (!thread_policy_setup) { 8132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka thread_policy_setup = 8142251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka SetThreadPolicy("graphics:high", "/system/performance"); 8152251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } 816bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 817b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 818bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (target_display_changed || just_resumed_running) { 819b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // Initialize the last vsync timestamp with the current time. The 820b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // predictor below uses this time + the vsync interval in absolute time 821b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // units for the initial delay. Once the driver starts reporting vsync the 822b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // predictor will sync up with the real vsync. 823b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka last_vsync_timestamp_ = GetSystemClockNs(); 824bfe46a053be03836a060853711b467ed5e10affaSteven Thomas vsync_prediction_interval_ = 1; 825bfe46a053be03836a060853711b467ed5e10affaSteven Thomas retire_fence_fds_.clear(); 826a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 827a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 828a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko int64_t vsync_timestamp = 0; 829a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko { 830b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka TRACE_FORMAT("wait_vsync|vsync=%u;last_timestamp=%" PRId64 831b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ";prediction_interval=%d|", 832b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka vsync_count_ + 1, last_vsync_timestamp_, 833b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka vsync_prediction_interval_); 834a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 835bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto status = WaitForPredictedVSync(); 836a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ALOGE_IF( 837b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka !status, 838a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko "HardwareComposer::PostThread: Failed to wait for vsync event: %s", 839b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka status.GetErrorMessage().c_str()); 840b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 841b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // If there was an error either sleeping was interrupted due to pausing or 842b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // there was an error getting the latest timestamp. 843b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka if (!status) 844a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko continue; 845b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 846b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // Predicted vsync timestamp for this interval. This is stable because we 847b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // use absolute time for the wakeup timer. 848b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka vsync_timestamp = status.get(); 849a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 850a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 851b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // Advance the vsync counter only if the system is keeping up with hardware 852b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // vsync to give clients an indication of the delays. 853b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka if (vsync_prediction_interval_ == 1) 854b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ++vsync_count_; 855a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 856bfe46a053be03836a060853711b467ed5e10affaSteven Thomas UpdateLayerConfig(); 857a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 858822b710a714c342dda0087f594c8ababa6630f44Okan Arikan // Publish the vsync event. 859822b710a714c342dda0087f594c8ababa6630f44Okan Arikan if (vsync_ring_) { 860822b710a714c342dda0087f594c8ababa6630f44Okan Arikan DvrVsync vsync; 861822b710a714c342dda0087f594c8ababa6630f44Okan Arikan vsync.vsync_count = vsync_count_; 862822b710a714c342dda0087f594c8ababa6630f44Okan Arikan vsync.vsync_timestamp_ns = vsync_timestamp; 863bfe46a053be03836a060853711b467ed5e10affaSteven Thomas vsync.vsync_left_eye_offset_ns = vsync_eye_offsets.left_ns; 864bfe46a053be03836a060853711b467ed5e10affaSteven Thomas vsync.vsync_right_eye_offset_ns = vsync_eye_offsets.right_ns; 865bfe46a053be03836a060853711b467ed5e10affaSteven Thomas vsync.vsync_period_ns = target_display_->vsync_period_ns; 866822b710a714c342dda0087f594c8ababa6630f44Okan Arikan 867822b710a714c342dda0087f594c8ababa6630f44Okan Arikan vsync_ring_->Publish(vsync); 868822b710a714c342dda0087f594c8ababa6630f44Okan Arikan } 869822b710a714c342dda0087f594c8ababa6630f44Okan Arikan 870a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // Signal all of the vsync clients. Because absolute time is used for the 871a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko // wakeup time below, this can take a little time if necessary. 872a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko if (vsync_callback_) 8736e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas vsync_callback_(vsync_timestamp, /*frame_time_estimate*/ 0, vsync_count_); 874a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 875a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko { 8762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // Sleep until shortly before vsync. 877a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ATRACE_NAME("sleep"); 878a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 879bfe46a053be03836a060853711b467ed5e10affaSteven Thomas const int64_t display_time_est_ns = 880bfe46a053be03836a060853711b467ed5e10affaSteven Thomas vsync_timestamp + target_display_->vsync_period_ns; 8812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka const int64_t now_ns = GetSystemClockNs(); 882954796e27e89209b38b35779949c243bec490c28John Bates const int64_t sleep_time_ns = display_time_est_ns - now_ns - 883954796e27e89209b38b35779949c243bec490c28John Bates post_thread_config_.frame_post_offset_ns; 884954796e27e89209b38b35779949c243bec490c28John Bates const int64_t wakeup_time_ns = 885954796e27e89209b38b35779949c243bec490c28John Bates display_time_est_ns - post_thread_config_.frame_post_offset_ns; 886a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 887a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ATRACE_INT64("sleep_time_ns", sleep_time_ns); 888a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko if (sleep_time_ns > 0) { 8892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka int error = SleepUntil(wakeup_time_ns); 8904668484104f28a30ada7c6906f05c818e82f9bf4John Bates ALOGE_IF(error < 0 && error != kPostThreadInterrupted, 8914668484104f28a30ada7c6906f05c818e82f9bf4John Bates "HardwareComposer::PostThread: Failed to sleep: %s", 892a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko strerror(-error)); 8934668484104f28a30ada7c6906f05c818e82f9bf4John Bates // If the sleep was interrupted (error == kPostThreadInterrupted), 8944668484104f28a30ada7c6906f05c818e82f9bf4John Bates // we still go through and present this frame because we may have set 8954668484104f28a30ada7c6906f05c818e82f9bf4John Bates // layers earlier and we want to flush the Composer's internal command 8964668484104f28a30ada7c6906f05c818e82f9bf4John Bates // buffer by continuing through to validate and present. 897a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 898a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 899a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 900b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka { 901bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto status = composer_callback_->GetVsyncTime(target_display_->id); 902b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 903b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // If we failed to read vsync there might be a problem with the driver. 904b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // Since there's nothing we can do just behave as though we didn't get an 905b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // updated vsync time and let the prediction continue. 906b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka const int64_t current_vsync_timestamp = 907b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka status ? status.get() : last_vsync_timestamp_; 908b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 909b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka const bool vsync_delayed = 910b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka last_vsync_timestamp_ == current_vsync_timestamp; 911b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ATRACE_INT("vsync_delayed", vsync_delayed); 912b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 913b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // If vsync was delayed advance the prediction interval and allow the 914b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // fence logic in PostLayers() to skip the frame. 915b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka if (vsync_delayed) { 916b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ALOGW( 917b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "HardwareComposer::PostThread: VSYNC timestamp did not advance " 918b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "since last frame: timestamp=%" PRId64 " prediction_interval=%d", 919b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka current_vsync_timestamp, vsync_prediction_interval_); 920b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka vsync_prediction_interval_++; 921b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } else { 922b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // We have an updated vsync timestamp, reset the prediction interval. 923b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka last_vsync_timestamp_ = current_vsync_timestamp; 924b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka vsync_prediction_interval_ = 1; 925b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } 926b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } 927b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 928bfe46a053be03836a060853711b467ed5e10affaSteven Thomas PostLayers(target_display_->id); 929a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 930a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 931a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 932bfe46a053be03836a060853711b467ed5e10affaSteven Thomasbool HardwareComposer::UpdateTargetDisplay() { 933bfe46a053be03836a060853711b467ed5e10affaSteven Thomas bool target_display_changed = false; 934bfe46a053be03836a060853711b467ed5e10affaSteven Thomas auto displays = composer_callback_->GetDisplays(); 935bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (displays.external_display_was_hotplugged) { 936bfe46a053be03836a060853711b467ed5e10affaSteven Thomas bool was_using_external_display = !target_display_->is_primary; 937bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (was_using_external_display) { 938bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // The external display was hotplugged, so make sure to ignore any bad 939bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // display errors as we destroy the layers. 940bfe46a053be03836a060853711b467ed5e10affaSteven Thomas for (auto& layer: layers_) 941bfe46a053be03836a060853711b467ed5e10affaSteven Thomas layer.IgnoreBadDisplayErrorsOnDestroy(true); 942bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 943bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 944bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (displays.external_display) { 945bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // External display was connected 946bfe46a053be03836a060853711b467ed5e10affaSteven Thomas external_display_ = GetDisplayParams(composer_.get(), 947bfe46a053be03836a060853711b467ed5e10affaSteven Thomas *displays.external_display, /*is_primary*/ false); 948bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 949bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (property_get_bool(kUseExternalDisplayProperty, false)) { 950bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI("External display connected. Switching to external display."); 951bfe46a053be03836a060853711b467ed5e10affaSteven Thomas target_display_ = &(*external_display_); 952bfe46a053be03836a060853711b467ed5e10affaSteven Thomas target_display_changed = true; 953bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } else { 954bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI("External display connected, but sysprop %s is unset, so" 955bfe46a053be03836a060853711b467ed5e10affaSteven Thomas " using primary display.", kUseExternalDisplayProperty); 956bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (was_using_external_display) { 957bfe46a053be03836a060853711b467ed5e10affaSteven Thomas target_display_ = &primary_display_; 958bfe46a053be03836a060853711b467ed5e10affaSteven Thomas target_display_changed = true; 959bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 960bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 961bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } else { 962bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // External display was disconnected 963bfe46a053be03836a060853711b467ed5e10affaSteven Thomas external_display_ = std::nullopt; 964bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (was_using_external_display) { 965bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI("External display disconnected. Switching to primary display."); 966bfe46a053be03836a060853711b467ed5e10affaSteven Thomas target_display_ = &primary_display_; 967bfe46a053be03836a060853711b467ed5e10affaSteven Thomas target_display_changed = true; 968bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 969bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 970bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 971bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 972bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (target_display_changed) { 973bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // If we're switching to the external display, turn the primary display off. 974bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (!target_display_->is_primary) { 975bfe46a053be03836a060853711b467ed5e10affaSteven Thomas EnableDisplay(primary_display_, false); 976bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 977bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // If we're switching to the primary display, and the external display is 978bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // still connected, turn the external display off. 979bfe46a053be03836a060853711b467ed5e10affaSteven Thomas else if (target_display_->is_primary && external_display_) { 980bfe46a053be03836a060853711b467ed5e10affaSteven Thomas EnableDisplay(*external_display_, false); 981bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 982bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 983bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // Turn the new target display on. 984bfe46a053be03836a060853711b467ed5e10affaSteven Thomas EnableDisplay(*target_display_, true); 985bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 986bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // When we switch displays we need to recreate all the layers, so clear the 987bfe46a053be03836a060853711b467ed5e10affaSteven Thomas // current list, which will trigger layer recreation. 988bfe46a053be03836a060853711b467ed5e10affaSteven Thomas layers_.clear(); 989bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 990bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 991bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return target_display_changed; 992bfe46a053be03836a060853711b467ed5e10affaSteven Thomas} 993bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 9942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// Checks for changes in the surface stack and updates the layer config to 9952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// accomodate the new stack. 996bfe46a053be03836a060853711b467ed5e10affaSteven Thomasvoid HardwareComposer::UpdateLayerConfig() { 9972251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces; 998050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas { 9992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka std::unique_lock<std::mutex> lock(post_thread_mutex_); 1000050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas 1001bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (!surfaces_changed_ && (!layers_.empty() || surfaces_.empty())) 1002bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return; 1003bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 1004bfe46a053be03836a060853711b467ed5e10affaSteven Thomas surfaces = surfaces_; 1005bfe46a053be03836a060853711b467ed5e10affaSteven Thomas surfaces_changed_ = false; 1006a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 1007a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1008a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko ATRACE_NAME("UpdateLayerConfig_HwLayers"); 1009a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 10102c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // Sort the new direct surface list by z-order to determine the relative order 10112c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // of the surfaces. This relative order is used for the HWC z-order value to 10122c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // insulate VrFlinger and HWC z-order semantics from each other. 10132c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) { 10142c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka return a->z_order() < b->z_order(); 10152c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka }); 1016a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 10172c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // Prepare a new layer stack, pulling in layers from the previous 10182c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // layer stack that are still active and updating their attributes. 10192c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka std::vector<Layer> layers; 10202c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka size_t layer_index = 0; 10212c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka for (const auto& surface : surfaces) { 10222251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // The bottom layer is opaque, other layers blend. 10232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka HWC::BlendMode blending = 10242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage; 1025a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 10262c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // Try to find a layer for this surface in the set of active layers. 10272c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka auto search = 10282c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka std::lower_bound(layers_.begin(), layers_.end(), surface->surface_id()); 10292c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka const bool found = search != layers_.end() && 10302c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka search->GetSurfaceId() == surface->surface_id(); 10312c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka if (found) { 10322c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // Update the attributes of the layer that may have changed. 10332c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka search->SetBlending(blending); 10342c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka search->SetZOrder(layer_index); // Relative z-order. 10352c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 10362c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // Move the existing layer to the new layer set and remove the empty layer 10372c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // object from the current set. 10382c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layers.push_back(std::move(*search)); 10392c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layers_.erase(search); 10402c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka } else { 10412c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // Insert a layer for the new surface. 1042bfe46a053be03836a060853711b467ed5e10affaSteven Thomas layers.emplace_back(composer_.get(), *target_display_, surface, blending, 1043bfe46a053be03836a060853711b467ed5e10affaSteven Thomas HWC::Composition::Device, layer_index); 10442c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka } 1045a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 10462c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka ALOGI_IF( 10472c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka TRACE, 10482c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka "HardwareComposer::UpdateLayerConfig: layer_index=%zu surface_id=%d", 10492c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layer_index, layers[layer_index].GetSurfaceId()); 10502c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 10512c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layer_index++; 10522c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka } 10532c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 10542c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // Sort the new layer stack by ascending surface id. 10552c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka std::sort(layers.begin(), layers.end()); 1056a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 10572c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // Replace the previous layer set with the new layer set. The destructor of 10582c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // the previous set will clean up the remaining Layers that are not moved to 10592c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // the new layer set. 10602c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layers_ = std::move(layers); 1061a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 10622c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers", 10632c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layers_.size()); 1064a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1065a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1066a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid HardwareComposer::SetVSyncCallback(VSyncCallback callback) { 1067a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko vsync_callback_ = callback; 1068a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1069a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1070b02664ddc146893e6bbe7939ee2b948d54e7166aSteven ThomasReturn<void> HardwareComposer::ComposerCallback::onHotplug( 10716e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas Hwc2::Display display, IComposerCallback::Connection conn) { 1072bfe46a053be03836a060853711b467ed5e10affaSteven Thomas std::lock_guard<std::mutex> lock(mutex_); 1073bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGI("onHotplug display=%" PRIu64 " conn=%d", display, conn); 1074bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 1075bfe46a053be03836a060853711b467ed5e10affaSteven Thomas bool is_primary = !got_first_hotplug_ || display == primary_display_.id; 1076bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 10776e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas // Our first onHotplug callback is always for the primary display. 1078bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (!got_first_hotplug_) { 10796e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas LOG_ALWAYS_FATAL_IF(conn != IComposerCallback::Connection::CONNECTED, 10806e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas "Initial onHotplug callback should be primary display connected"); 1081bfe46a053be03836a060853711b467ed5e10affaSteven Thomas got_first_hotplug_ = true; 1082bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } else if (is_primary) { 1083bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGE("Ignoring unexpected onHotplug() call for primary display"); 1084bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return Void(); 1085bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 1086bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 1087bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (conn == IComposerCallback::Connection::CONNECTED) { 1088bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (!is_primary) 1089bfe46a053be03836a060853711b467ed5e10affaSteven Thomas external_display_ = DisplayInfo(); 1090bfe46a053be03836a060853711b467ed5e10affaSteven Thomas DisplayInfo& display_info = is_primary ? 1091bfe46a053be03836a060853711b467ed5e10affaSteven Thomas primary_display_ : *external_display_; 1092bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display_info.id = display; 10936e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas 1094b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka std::array<char, 1024> buffer; 1095b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka snprintf(buffer.data(), buffer.size(), 1096b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "/sys/class/graphics/fb%" PRIu64 "/vsync_event", display); 1097b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka if (LocalHandle handle{buffer.data(), O_RDONLY}) { 1098b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ALOGI( 1099b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "HardwareComposer::ComposerCallback::onHotplug: Driver supports " 1100b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "vsync_event node for display %" PRIu64, 1101b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka display); 1102bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display_info.driver_vsync_event_fd = std::move(handle); 1103b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } else { 1104b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ALOGI( 1105b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "HardwareComposer::ComposerCallback::onHotplug: Driver does not " 1106b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "support vsync_event node for display %" PRIu64, 1107b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka display); 1108b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } 1109bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } else if (conn == IComposerCallback::Connection::DISCONNECTED) { 1110bfe46a053be03836a060853711b467ed5e10affaSteven Thomas external_display_ = std::nullopt; 1111b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } 1112b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 1113bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (!is_primary) 1114bfe46a053be03836a060853711b467ed5e10affaSteven Thomas external_display_was_hotplugged_ = true; 1115bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 1116b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas return Void(); 1117a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1118a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1119b02664ddc146893e6bbe7939ee2b948d54e7166aSteven ThomasReturn<void> HardwareComposer::ComposerCallback::onRefresh( 1120b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas Hwc2::Display /*display*/) { 1121b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas return hardware::Void(); 11223cfac28462910d3f976aebac54ac7301aca7e434Steven Thomas} 11233cfac28462910d3f976aebac54ac7301aca7e434Steven Thomas 1124451256f7f908fe4b87a29fd3d325251f34d53729Corey TabakaReturn<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display, 1125451256f7f908fe4b87a29fd3d325251f34d53729Corey Tabaka int64_t timestamp) { 1126bfe46a053be03836a060853711b467ed5e10affaSteven Thomas DisplayInfo* display_info = GetDisplayInfo(display); 1127bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (display_info) { 11286e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|", 11296e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas display, timestamp); 1130bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display_info->callback_vsync_timestamp = timestamp; 1131a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 1132bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 1133b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas return Void(); 1134b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas} 1135b02664ddc146893e6bbe7939ee2b948d54e7166aSteven Thomas 1136bfe46a053be03836a060853711b467ed5e10affaSteven ThomasHardwareComposer::ComposerCallback::Displays 1137bfe46a053be03836a060853711b467ed5e10affaSteven ThomasHardwareComposer::ComposerCallback::GetDisplays() { 1138bfe46a053be03836a060853711b467ed5e10affaSteven Thomas std::lock_guard<std::mutex> lock(mutex_); 1139bfe46a053be03836a060853711b467ed5e10affaSteven Thomas Displays displays; 1140bfe46a053be03836a060853711b467ed5e10affaSteven Thomas displays.primary_display = primary_display_.id; 1141bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (external_display_) 1142bfe46a053be03836a060853711b467ed5e10affaSteven Thomas displays.external_display = external_display_->id; 1143bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (external_display_was_hotplugged_) { 1144bfe46a053be03836a060853711b467ed5e10affaSteven Thomas external_display_was_hotplugged_ = false; 1145bfe46a053be03836a060853711b467ed5e10affaSteven Thomas displays.external_display_was_hotplugged = true; 1146bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 1147bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return displays; 1148bfe46a053be03836a060853711b467ed5e10affaSteven Thomas} 1149bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 1150bfe46a053be03836a060853711b467ed5e10affaSteven ThomasStatus<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime( 1151bfe46a053be03836a060853711b467ed5e10affaSteven Thomas hwc2_display_t display) { 1152bfe46a053be03836a060853711b467ed5e10affaSteven Thomas DisplayInfo* display_info = GetDisplayInfo(display); 1153bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (!display_info) { 1154bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGW("Attempt to get vsync time for unknown display %" PRIu64, display); 1155bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return ErrorStatus(EINVAL); 1156bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 1157bfe46a053be03836a060853711b467ed5e10affaSteven Thomas 1158b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // See if the driver supports direct vsync events. 1159bfe46a053be03836a060853711b467ed5e10affaSteven Thomas LocalHandle& event_fd = display_info->driver_vsync_event_fd; 1160b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka if (!event_fd) { 1161b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // Fall back to returning the last timestamp returned by the vsync 1162b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // callback. 1163bfe46a053be03836a060853711b467ed5e10affaSteven Thomas std::lock_guard<std::mutex> autolock(mutex_); 1164bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return display_info->callback_vsync_timestamp; 1165b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } 1166b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 1167b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // When the driver supports the vsync_event sysfs node we can use it to 1168b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // determine the latest vsync timestamp, even if the HWC callback has been 1169b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // delayed. 1170b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 1171b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // The driver returns data in the form "VSYNC=<timestamp ns>". 1172b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka std::array<char, 32> data; 1173b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka data.fill('\0'); 1174b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 1175b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // Seek back to the beginning of the event file. 1176b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka int ret = lseek(event_fd.Get(), 0, SEEK_SET); 1177b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka if (ret < 0) { 1178b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka const int error = errno; 1179b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ALOGE( 1180b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "HardwareComposer::ComposerCallback::GetVsyncTime: Failed to seek " 1181b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "vsync event fd: %s", 1182b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka strerror(error)); 1183b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka return ErrorStatus(error); 1184b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } 1185b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 1186b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka // Read the vsync event timestamp. 1187b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ret = read(event_fd.Get(), data.data(), data.size()); 1188b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka if (ret < 0) { 1189b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka const int error = errno; 1190b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ALOGE_IF(error != EAGAIN, 1191b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "HardwareComposer::ComposerCallback::GetVsyncTime: Error " 1192b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "while reading timestamp: %s", 1193b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka strerror(error)); 1194b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka return ErrorStatus(error); 1195b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } 1196b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka 1197b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka int64_t timestamp; 1198b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ret = sscanf(data.data(), "VSYNC=%" PRIu64, 1199b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka reinterpret_cast<uint64_t*>(×tamp)); 1200b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka if (ret < 0) { 1201b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka const int error = errno; 1202b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka ALOGE( 1203b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "HardwareComposer::ComposerCallback::GetVsyncTime: Error while " 1204b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka "parsing timestamp: %s", 1205b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka strerror(error)); 1206b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka return ErrorStatus(error); 1207b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka } 1208a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1209b3732f08c0655998b2f31c76aac8595a343b511eCorey Tabaka return {timestamp}; 1210a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1211a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1212bfe46a053be03836a060853711b467ed5e10affaSteven ThomasHardwareComposer::ComposerCallback::DisplayInfo* 1213bfe46a053be03836a060853711b467ed5e10affaSteven ThomasHardwareComposer::ComposerCallback::GetDisplayInfo(hwc2_display_t display) { 1214bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (display == primary_display_.id) { 1215bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return &primary_display_; 1216bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } else if (external_display_ && display == external_display_->id) { 1217bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return &(*external_display_); 1218bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 1219bfe46a053be03836a060853711b467ed5e10affaSteven Thomas return nullptr; 1220bfe46a053be03836a060853711b467ed5e10affaSteven Thomas} 12212c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 1222a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid Layer::Reset() { 12232c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka if (hardware_composer_layer_) { 1224bfe46a053be03836a060853711b467ed5e10affaSteven Thomas HWC::Error error = 1225bfe46a053be03836a060853711b467ed5e10affaSteven Thomas composer_->destroyLayer(display_params_.id, hardware_composer_layer_); 1226bfe46a053be03836a060853711b467ed5e10affaSteven Thomas if (error != HWC::Error::None && 1227bfe46a053be03836a060853711b467ed5e10affaSteven Thomas (!ignore_bad_display_errors_on_destroy_ || 1228bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error != HWC::Error::BadDisplay)) { 1229bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ALOGE("destroyLayer() failed for display %" PRIu64 ", layer %" PRIu64 1230bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ". error: %s", display_params_.id, hardware_composer_layer_, 1231bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error.to_string().c_str()); 1232bfe46a053be03836a060853711b467ed5e10affaSteven Thomas } 1233a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko hardware_composer_layer_ = 0; 1234a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 1235a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 12362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka z_order_ = 0; 12372251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka blending_ = HWC::BlendMode::None; 12382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka composition_type_ = HWC::Composition::Invalid; 12392251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka target_composition_type_ = composition_type_; 12402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka source_ = EmptyVariant{}; 12412251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka acquire_fence_.Close(); 1242a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko surface_rect_functions_applied_ = false; 12432c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka pending_visibility_settings_ = true; 12440d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka cached_buffer_map_.clear(); 1245bfe46a053be03836a060853711b467ed5e10affaSteven Thomas ignore_bad_display_errors_on_destroy_ = false; 1246a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1247a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1248bfe46a053be03836a060853711b467ed5e10affaSteven ThomasLayer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params, 1249bfe46a053be03836a060853711b467ed5e10affaSteven Thomas const std::shared_ptr<DirectDisplaySurface>& surface, 1250bfe46a053be03836a060853711b467ed5e10affaSteven Thomas HWC::BlendMode blending, HWC::Composition composition_type, 1251bfe46a053be03836a060853711b467ed5e10affaSteven Thomas size_t z_order) 1252bfe46a053be03836a060853711b467ed5e10affaSteven Thomas : composer_(composer), 1253bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display_params_(display_params), 1254bfe46a053be03836a060853711b467ed5e10affaSteven Thomas z_order_{z_order}, 12552c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka blending_{blending}, 12562c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka target_composition_type_{composition_type}, 12572c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka source_{SourceSurface{surface}} { 12582c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka CommonLayerSetup(); 1259a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1260a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1261bfe46a053be03836a060853711b467ed5e10affaSteven ThomasLayer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params, 1262bfe46a053be03836a060853711b467ed5e10affaSteven Thomas const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending, 1263bfe46a053be03836a060853711b467ed5e10affaSteven Thomas HWC::Composition composition_type, size_t z_order) 1264bfe46a053be03836a060853711b467ed5e10affaSteven Thomas : composer_(composer), 1265bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display_params_(display_params), 1266bfe46a053be03836a060853711b467ed5e10affaSteven Thomas z_order_{z_order}, 12672c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka blending_{blending}, 12682c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka target_composition_type_{composition_type}, 12692c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka source_{SourceBuffer{buffer}} { 12702c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka CommonLayerSetup(); 12712c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka} 12722c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 12732c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey TabakaLayer::~Layer() { Reset(); } 12742c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 12752c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey TabakaLayer::Layer(Layer&& other) { *this = std::move(other); } 12762c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 12772c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey TabakaLayer& Layer::operator=(Layer&& other) { 12782c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka if (this != &other) { 12792c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka Reset(); 12802c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka using std::swap; 1281bfe46a053be03836a060853711b467ed5e10affaSteven Thomas swap(composer_, other.composer_); 1282bfe46a053be03836a060853711b467ed5e10affaSteven Thomas swap(display_params_, other.display_params_); 12832c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka swap(hardware_composer_layer_, other.hardware_composer_layer_); 12842c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka swap(z_order_, other.z_order_); 12852c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka swap(blending_, other.blending_); 12862c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka swap(composition_type_, other.composition_type_); 12872c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka swap(target_composition_type_, other.target_composition_type_); 12882c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka swap(source_, other.source_); 12892c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka swap(acquire_fence_, other.acquire_fence_); 12902c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka swap(surface_rect_functions_applied_, 12912c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka other.surface_rect_functions_applied_); 12922c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka swap(pending_visibility_settings_, other.pending_visibility_settings_); 12930d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka swap(cached_buffer_map_, other.cached_buffer_map_); 1294bfe46a053be03836a060853711b467ed5e10affaSteven Thomas swap(ignore_bad_display_errors_on_destroy_, 1295bfe46a053be03836a060853711b467ed5e10affaSteven Thomas other.ignore_bad_display_errors_on_destroy_); 12962c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka } 12972c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka return *this; 1298a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1299a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 13002251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) { 13012251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (source_.is<SourceBuffer>()) 13022251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka std::get<SourceBuffer>(source_) = {buffer}; 1303a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1304a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 13052c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabakavoid Layer::SetBlending(HWC::BlendMode blending) { 13062c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka if (blending_ != blending) { 13072c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka blending_ = blending; 13082c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka pending_visibility_settings_ = true; 13092c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka } 13102c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka} 13112c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 13122c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabakavoid Layer::SetZOrder(size_t z_order) { 13132c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka if (z_order_ != z_order) { 13142c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka z_order_ = z_order; 13152c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka pending_visibility_settings_ = true; 13162c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka } 13172c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka} 1318a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1319a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex VakulenkoIonBuffer* Layer::GetBuffer() { 13202251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka struct Visitor { 13212251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); } 13222251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); } 13232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka IonBuffer* operator()(EmptyVariant) { return nullptr; } 13242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka }; 13252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka return source_.Visit(Visitor{}); 1326a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1327a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 13282c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabakavoid Layer::UpdateVisibilitySettings() { 13292c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka if (pending_visibility_settings_) { 13302c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka pending_visibility_settings_ = false; 13312c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 13322c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka HWC::Error error; 13332c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 13342c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka error = composer_->setLayerBlendMode( 1335bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display_params_.id, hardware_composer_layer_, 13362c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka blending_.cast<Hwc2::IComposerClient::BlendMode>()); 13372c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka ALOGE_IF(error != HWC::Error::None, 13382c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka "Layer::UpdateLayerSettings: Error setting layer blend mode: %s", 13392c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka error.to_string().c_str()); 13402c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 1341bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error = composer_->setLayerZOrder(display_params_.id, 1342bfe46a053be03836a060853711b467ed5e10affaSteven Thomas hardware_composer_layer_, z_order_); 13432c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka ALOGE_IF(error != HWC::Error::None, 13442c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka "Layer::UpdateLayerSettings: Error setting z_ order: %s", 13452c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka error.to_string().c_str()); 1346a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 13472c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka} 1348a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 13492c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabakavoid Layer::UpdateLayerSettings() { 13502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka HWC::Error error; 1351a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 13522c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka UpdateVisibilitySettings(); 13532c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 13542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // TODO(eieio): Use surface attributes or some other mechanism to control 13552251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // the layer display frame. 13562c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka error = composer_->setLayerDisplayFrame( 1357bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display_params_.id, hardware_composer_layer_, 1358bfe46a053be03836a060853711b467ed5e10affaSteven Thomas {0, 0, display_params_.width, display_params_.height}); 13592251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGE_IF(error != HWC::Error::None, 13602251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka "Layer::UpdateLayerSettings: Error setting layer display frame: %s", 13612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka error.to_string().c_str()); 13622251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 13632c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka error = composer_->setLayerVisibleRegion( 1364bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display_params_.id, hardware_composer_layer_, 1365bfe46a053be03836a060853711b467ed5e10affaSteven Thomas {{0, 0, display_params_.width, display_params_.height}}); 13662251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGE_IF(error != HWC::Error::None, 13672251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka "Layer::UpdateLayerSettings: Error setting layer visible region: %s", 13682251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka error.to_string().c_str()); 13692251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 1370bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error = composer_->setLayerPlaneAlpha(display_params_.id, 1371bfe46a053be03836a060853711b467ed5e10affaSteven Thomas hardware_composer_layer_, 1.0f); 13722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGE_IF(error != HWC::Error::None, 13732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s", 13742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka error.to_string().c_str()); 1375a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1376a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 13772c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabakavoid Layer::CommonLayerSetup() { 1378bfe46a053be03836a060853711b467ed5e10affaSteven Thomas HWC::Error error = composer_->createLayer(display_params_.id, 13796e8f706c21a01d6a1225e86972ff432bba5f0106Steven Thomas &hardware_composer_layer_); 13802c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka ALOGE_IF(error != HWC::Error::None, 13812c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka "Layer::CommonLayerSetup: Failed to create layer on primary " 13822c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka "display: %s", 13832c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka error.to_string().c_str()); 13842c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka UpdateLayerSettings(); 1385a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1386a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 13870d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabakabool Layer::CheckAndUpdateCachedBuffer(std::size_t slot, int buffer_id) { 13880d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka auto search = cached_buffer_map_.find(slot); 13890d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka if (search != cached_buffer_map_.end() && search->second == buffer_id) 13900d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka return true; 13910d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka 13920d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka // Assign or update the buffer slot. 13930d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka if (buffer_id >= 0) 13940d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka cached_buffer_map_[slot] = buffer_id; 13950d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka return false; 13960d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka} 13970d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka 1398a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid Layer::Prepare() { 13990d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka int right, bottom, id; 14001f42e3a02c4f9a1ba1916a2f0e47082bedb73e41Daniel Nicoara sp<GraphicBuffer> handle; 14010d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka std::size_t slot; 1402a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 14032251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // Acquire the next buffer according to the type of source. 14042251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) { 14050d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka std::tie(right, bottom, id, handle, acquire_fence_, slot) = 14060d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka source.Acquire(); 14072251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka }); 14082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka 14090d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka TRACE_FORMAT("Layer::Prepare|buffer_id=%d;slot=%zu|", id, slot); 14100d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka 14112c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // Update any visibility (blending, z-order) changes that occurred since 14122c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // last prepare. 14132c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka UpdateVisibilitySettings(); 14142c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka 14152c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // When a layer is first setup there may be some time before the first 14162c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // buffer arrives. Setup the HWC layer as a solid color to stall for time 14172c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // until the first buffer arrives. Once the first buffer arrives there will 14182c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka // always be a buffer for the frame even if it is old. 14192251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (!handle.get()) { 14202251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (composition_type_ == HWC::Composition::Invalid) { 14212251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka composition_type_ = HWC::Composition::SolidColor; 14222c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka composer_->setLayerCompositionType( 1423bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display_params_.id, hardware_composer_layer_, 14242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka composition_type_.cast<Hwc2::IComposerClient::Composition>()); 14252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0}; 1426bfe46a053be03836a060853711b467ed5e10affaSteven Thomas composer_->setLayerColor(display_params_.id, hardware_composer_layer_, 14272c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka layer_color); 14282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } else { 14292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // The composition type is already set. Nothing else to do until a 14302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka // buffer arrives. 1431a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 1432a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } else { 14332251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (composition_type_ != target_composition_type_) { 14342251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka composition_type_ = target_composition_type_; 14352c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka composer_->setLayerCompositionType( 1436bfe46a053be03836a060853711b467ed5e10affaSteven Thomas display_params_.id, hardware_composer_layer_, 14372251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka composition_type_.cast<Hwc2::IComposerClient::Composition>()); 14382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } 1439a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 14400d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka // See if the HWC cache already has this buffer. 14410d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka const bool cached = CheckAndUpdateCachedBuffer(slot, id); 14420d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka if (cached) 14430d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka handle = nullptr; 14440d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka 14452251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka HWC::Error error{HWC::Error::None}; 14462c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka error = 1447bfe46a053be03836a060853711b467ed5e10affaSteven Thomas composer_->setLayerBuffer(display_params_.id, hardware_composer_layer_, 14480d07cdd593f982e5f6e75706c7f9a99a3c5a9264Corey Tabaka slot, handle, acquire_fence_.Get()); 1449a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 14502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGE_IF(error != HWC::Error::None, 14512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka "Layer::Prepare: Error setting layer buffer: %s", 14522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka error.to_string().c_str()); 1453a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 14542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka if (!surface_rect_functions_applied_) { 14552251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka const float float_right = right; 14562251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka const float float_bottom = bottom; 1457bfe46a053be03836a060853711b467ed5e10affaSteven Thomas error = composer_->setLayerSourceCrop(display_params_.id, 14582c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka hardware_composer_layer_, 14592c4aea369d9ec77e98c6b9c08e6feb25fc5a20d2Corey Tabaka {0, 0, float_right, float_bottom}); 1460a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 14612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka ALOGE_IF(error != HWC::Error::None, 14622251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka "Layer::Prepare: Error setting layer source crop: %s", 14632251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka error.to_string().c_str()); 1464a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 14652251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka surface_rect_functions_applied_ = true; 14662251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka } 1467a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko } 1468a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1469a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1470a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid Layer::Finish(int release_fence_fd) { 14712251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka IfAnyOf<SourceSurface, SourceBuffer>::Call( 14722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka &source_, [release_fence_fd](auto& source) { 14732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka source.Finish(LocalHandle(release_fence_fd)); 14742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka }); 1475a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} 1476a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 14772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid Layer::Drop() { acquire_fence_.Close(); } 1478a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko 1479a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} // namespace dvr 1480a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko} // namespace android 1481