blob: c19fb249dd20fc934af24816613a2d245b4ac036 [file] [log] [blame]
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001#include "hardware_composer.h"
2
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08003#include <cutils/properties.h>
4#include <cutils/sched_policy.h>
5#include <fcntl.h>
Corey Tabaka2251d822017-04-20 16:04:07 -07006#include <log/log.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08007#include <poll.h>
8#include <sync/sync.h>
9#include <sys/eventfd.h>
10#include <sys/prctl.h>
11#include <sys/resource.h>
12#include <sys/system_properties.h>
13#include <sys/timerfd.h>
Corey Tabaka2251d822017-04-20 16:04:07 -070014#include <time.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080015#include <unistd.h>
16#include <utils/Trace.h>
17
18#include <algorithm>
Corey Tabaka2251d822017-04-20 16:04:07 -070019#include <chrono>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080020#include <functional>
21#include <map>
Corey Tabaka0b485c92017-05-19 12:02:58 -070022#include <sstream>
23#include <string>
John Bates954796e2017-05-11 11:00:31 -070024#include <tuple>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080025
Corey Tabaka2251d822017-04-20 16:04:07 -070026#include <dvr/dvr_display_types.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080027#include <dvr/performance_client_api.h>
28#include <private/dvr/clock_ns.h>
Corey Tabaka2251d822017-04-20 16:04:07 -070029#include <private/dvr/ion_buffer.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080030
Steven Thomasd7f49c52017-07-26 18:48:28 -070031using android::hardware::Return;
32using android::hardware::Void;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080033using android::pdx::LocalHandle;
Corey Tabaka2251d822017-04-20 16:04:07 -070034using android::pdx::rpc::EmptyVariant;
35using android::pdx::rpc::IfAnyOf;
36
37using namespace std::chrono_literals;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080038
39namespace android {
40namespace dvr {
41
42namespace {
43
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080044const char kBacklightBrightnessSysFile[] =
45 "/sys/class/leds/lcd-backlight/brightness";
46
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080047const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
48
49const char kDvrPerformanceProperty[] = "sys.dvr.performance";
50
Luke Song4b788322017-03-24 14:17:31 -070051const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080052
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080053// Get time offset from a vsync to when the pose for that vsync should be
54// predicted out to. For example, if scanout gets halfway through the frame
55// at the halfway point between vsyncs, then this could be half the period.
56// With global shutter displays, this should be changed to the offset to when
57// illumination begins. Low persistence adds a frame of latency, so we predict
58// to the center of the next frame.
59inline int64_t GetPosePredictionTimeOffset(int64_t vsync_period_ns) {
60 return (vsync_period_ns * 150) / 100;
61}
62
Corey Tabaka2251d822017-04-20 16:04:07 -070063// Attempts to set the scheduler class and partiton for the current thread.
64// Returns true on success or false on failure.
65bool SetThreadPolicy(const std::string& scheduler_class,
66 const std::string& partition) {
67 int error = dvrSetSchedulerClass(0, scheduler_class.c_str());
68 if (error < 0) {
69 ALOGE(
70 "SetThreadPolicy: Failed to set scheduler class \"%s\" for "
71 "thread_id=%d: %s",
72 scheduler_class.c_str(), gettid(), strerror(-error));
73 return false;
74 }
75 error = dvrSetCpuPartition(0, partition.c_str());
76 if (error < 0) {
77 ALOGE(
78 "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: "
79 "%s",
80 partition.c_str(), gettid(), strerror(-error));
81 return false;
82 }
83 return true;
84}
85
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080086} // anonymous namespace
87
Corey Tabaka2251d822017-04-20 16:04:07 -070088HardwareComposer::HardwareComposer()
Steven Thomasd7f49c52017-07-26 18:48:28 -070089 : initialized_(false), request_display_callback_(nullptr) {}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080090
91HardwareComposer::~HardwareComposer(void) {
Corey Tabaka2251d822017-04-20 16:04:07 -070092 UpdatePostThreadState(PostThreadState::Quit, true);
93 if (post_thread_.joinable())
Steven Thomas050b2c82017-03-06 11:45:16 -080094 post_thread_.join();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080095}
96
Steven Thomasd7f49c52017-07-26 18:48:28 -070097bool HardwareComposer::Initialize(
Corey Tabaka2c4aea32017-08-31 20:01:15 -070098 Hwc2::Composer* composer, RequestDisplayCallback request_display_callback) {
Stephen Kiazyk016e5e32017-02-21 17:09:22 -080099 if (initialized_) {
100 ALOGE("HardwareComposer::Initialize: already initialized.");
101 return false;
102 }
103
Steven Thomasd7f49c52017-07-26 18:48:28 -0700104 request_display_callback_ = request_display_callback;
105
Corey Tabaka2251d822017-04-20 16:04:07 -0700106 HWC::Error error = HWC::Error::None;
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800107
108 Hwc2::Config config;
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700109 error = composer->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800110
Corey Tabaka2251d822017-04-20 16:04:07 -0700111 if (error != HWC::Error::None) {
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800112 ALOGE("HardwareComposer: Failed to get current display config : %d",
113 config);
114 return false;
115 }
116
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700117 error = GetDisplayMetrics(composer, HWC_DISPLAY_PRIMARY, config,
Steven Thomasd7f49c52017-07-26 18:48:28 -0700118 &native_display_metrics_);
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800119
Corey Tabaka2251d822017-04-20 16:04:07 -0700120 if (error != HWC::Error::None) {
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800121 ALOGE(
122 "HardwareComposer: Failed to get display attributes for current "
123 "configuration : %d",
Corey Tabaka2251d822017-04-20 16:04:07 -0700124 error.value);
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800125 return false;
126 }
127
128 ALOGI(
129 "HardwareComposer: primary display attributes: width=%d height=%d "
130 "vsync_period_ns=%d DPI=%dx%d",
131 native_display_metrics_.width, native_display_metrics_.height,
132 native_display_metrics_.vsync_period_ns, native_display_metrics_.dpi.x,
133 native_display_metrics_.dpi.y);
134
135 // Set the display metrics but never use rotation to avoid the long latency of
136 // rotation processing in hwc.
137 display_transform_ = HWC_TRANSFORM_NONE;
138 display_metrics_ = native_display_metrics_;
139
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700140 // Setup the display metrics used by all Layer instances.
141 Layer::SetDisplayMetrics(native_display_metrics_);
142
Corey Tabaka2251d822017-04-20 16:04:07 -0700143 post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
Steven Thomas050b2c82017-03-06 11:45:16 -0800144 LOG_ALWAYS_FATAL_IF(
Corey Tabaka2251d822017-04-20 16:04:07 -0700145 !post_thread_event_fd_,
Steven Thomas050b2c82017-03-06 11:45:16 -0800146 "HardwareComposer: Failed to create interrupt event fd : %s",
147 strerror(errno));
148
149 post_thread_ = std::thread(&HardwareComposer::PostThread, this);
150
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800151 initialized_ = true;
152
153 return initialized_;
154}
155
Steven Thomas050b2c82017-03-06 11:45:16 -0800156void HardwareComposer::Enable() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700157 UpdatePostThreadState(PostThreadState::Suspended, false);
Steven Thomas050b2c82017-03-06 11:45:16 -0800158}
159
160void HardwareComposer::Disable() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700161 UpdatePostThreadState(PostThreadState::Suspended, true);
Steven Thomas050b2c82017-03-06 11:45:16 -0800162}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800163
Corey Tabaka2251d822017-04-20 16:04:07 -0700164// Update the post thread quiescent state based on idle and suspended inputs.
165void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
166 bool suspend) {
167 std::unique_lock<std::mutex> lock(post_thread_mutex_);
168
169 // Update the votes in the state variable before evaluating the effective
170 // quiescent state. Any bits set in post_thread_state_ indicate that the post
171 // thread should be suspended.
172 if (suspend) {
173 post_thread_state_ |= state;
174 } else {
175 post_thread_state_ &= ~state;
176 }
177
178 const bool quit = post_thread_state_ & PostThreadState::Quit;
179 const bool effective_suspend = post_thread_state_ != PostThreadState::Active;
180 if (quit) {
181 post_thread_quiescent_ = true;
182 eventfd_write(post_thread_event_fd_.Get(), 1);
183 post_thread_wait_.notify_one();
184 } else if (effective_suspend && !post_thread_quiescent_) {
185 post_thread_quiescent_ = true;
186 eventfd_write(post_thread_event_fd_.Get(), 1);
187 } else if (!effective_suspend && post_thread_quiescent_) {
188 post_thread_quiescent_ = false;
189 eventfd_t value;
190 eventfd_read(post_thread_event_fd_.Get(), &value);
191 post_thread_wait_.notify_one();
192 }
193
194 // Wait until the post thread is in the requested state.
195 post_thread_ready_.wait(lock, [this, effective_suspend] {
196 return effective_suspend != post_thread_resumed_;
197 });
Steven Thomas050b2c82017-03-06 11:45:16 -0800198}
Steven Thomas282a5ed2017-02-07 18:07:01 -0800199
Steven Thomas050b2c82017-03-06 11:45:16 -0800200void HardwareComposer::OnPostThreadResumed() {
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700201 composer_.reset(new Hwc2::Composer(false));
202 composer_callback_ = new ComposerCallback;
203 composer_->registerCallback(composer_callback_);
204 Layer::SetComposer(composer_.get());
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700205
Steven Thomas050b2c82017-03-06 11:45:16 -0800206 EnableVsync(true);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800207
Steven Thomas050b2c82017-03-06 11:45:16 -0800208 // TODO(skiazyk): We need to do something about accessing this directly,
209 // supposedly there is a backlight service on the way.
210 // TODO(steventhomas): When we change the backlight setting, will surface
211 // flinger (or something else) set it back to its original value once we give
212 // control of the display back to surface flinger?
213 SetBacklightBrightness(255);
Steven Thomas282a5ed2017-02-07 18:07:01 -0800214
Steven Thomas050b2c82017-03-06 11:45:16 -0800215 // Trigger target-specific performance mode change.
216 property_set(kDvrPerformanceProperty, "performance");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800217}
218
Steven Thomas050b2c82017-03-06 11:45:16 -0800219void HardwareComposer::OnPostThreadPaused() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700220 retire_fence_fds_.clear();
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700221 layers_.clear();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800222
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700223 if (composer_) {
Steven Thomasd7f49c52017-07-26 18:48:28 -0700224 EnableVsync(false);
225 }
Steven Thomas050b2c82017-03-06 11:45:16 -0800226
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700227 composer_callback_ = nullptr;
228 composer_.reset(nullptr);
229 Layer::SetComposer(nullptr);
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700230
Steven Thomas050b2c82017-03-06 11:45:16 -0800231 // Trigger target-specific performance mode change.
232 property_set(kDvrPerformanceProperty, "idle");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800233}
234
Corey Tabaka2251d822017-04-20 16:04:07 -0700235HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800236 uint32_t num_types;
237 uint32_t num_requests;
Corey Tabaka2251d822017-04-20 16:04:07 -0700238 HWC::Error error =
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700239 composer_->validateDisplay(display, &num_types, &num_requests);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800240
241 if (error == HWC2_ERROR_HAS_CHANGES) {
242 // TODO(skiazyk): We might need to inspect the requested changes first, but
243 // so far it seems like we shouldn't ever hit a bad state.
244 // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
245 // display);
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700246 error = composer_->acceptDisplayChanges(display);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800247 }
248
249 return error;
250}
251
Steven Thomasd7f49c52017-07-26 18:48:28 -0700252HWC::Error HardwareComposer::EnableVsync(bool enabled) {
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700253 return composer_->setVsyncEnabled(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800254 HWC_DISPLAY_PRIMARY,
255 (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
256 : HWC2_VSYNC_DISABLE));
257}
258
Corey Tabaka2251d822017-04-20 16:04:07 -0700259HWC::Error HardwareComposer::Present(hwc2_display_t display) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800260 int32_t present_fence;
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700261 HWC::Error error = composer_->presentDisplay(display, &present_fence);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800262
263 // According to the documentation, this fence is signaled at the time of
264 // vsync/DMA for physical displays.
Corey Tabaka2251d822017-04-20 16:04:07 -0700265 if (error == HWC::Error::None) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800266 ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
267 retire_fence_fds_.emplace_back(present_fence);
268 } else {
269 ATRACE_INT("HardwareComposer: PresentResult", error);
270 }
271
272 return error;
273}
274
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700275HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* composer,
Steven Thomasd7f49c52017-07-26 18:48:28 -0700276 hwc2_display_t display,
Corey Tabaka2251d822017-04-20 16:04:07 -0700277 hwc2_config_t config,
278 hwc2_attribute_t attribute,
279 int32_t* out_value) const {
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700280 return composer->getDisplayAttribute(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800281 display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
282}
283
Corey Tabaka2251d822017-04-20 16:04:07 -0700284HWC::Error HardwareComposer::GetDisplayMetrics(
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700285 Hwc2::Composer* composer, hwc2_display_t display, hwc2_config_t config,
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800286 HWCDisplayMetrics* out_metrics) const {
Corey Tabaka2251d822017-04-20 16:04:07 -0700287 HWC::Error error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800288
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700289 error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_WIDTH,
Corey Tabaka2251d822017-04-20 16:04:07 -0700290 &out_metrics->width);
291 if (error != HWC::Error::None) {
292 ALOGE(
293 "HardwareComposer::GetDisplayMetrics: Failed to get display width: %s",
294 error.to_string().c_str());
295 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800296 }
297
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700298 error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_HEIGHT,
Corey Tabaka2251d822017-04-20 16:04:07 -0700299 &out_metrics->height);
300 if (error != HWC::Error::None) {
301 ALOGE(
302 "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
303 error.to_string().c_str());
304 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800305 }
306
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700307 error = GetDisplayAttribute(composer, display, config,
Steven Thomasd7f49c52017-07-26 18:48:28 -0700308 HWC2_ATTRIBUTE_VSYNC_PERIOD,
Corey Tabaka2251d822017-04-20 16:04:07 -0700309 &out_metrics->vsync_period_ns);
310 if (error != HWC::Error::None) {
311 ALOGE(
312 "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
313 error.to_string().c_str());
314 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800315 }
316
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700317 error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_X,
Corey Tabaka2251d822017-04-20 16:04:07 -0700318 &out_metrics->dpi.x);
319 if (error != HWC::Error::None) {
320 ALOGE(
321 "HardwareComposer::GetDisplayMetrics: Failed to get display DPI X: %s",
322 error.to_string().c_str());
323 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800324 }
325
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700326 error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_Y,
Corey Tabaka2251d822017-04-20 16:04:07 -0700327 &out_metrics->dpi.y);
328 if (error != HWC::Error::None) {
329 ALOGE(
330 "HardwareComposer::GetDisplayMetrics: Failed to get display DPI Y: %s",
331 error.to_string().c_str());
332 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800333 }
334
Corey Tabaka2251d822017-04-20 16:04:07 -0700335 return HWC::Error::None;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800336}
337
Corey Tabaka0b485c92017-05-19 12:02:58 -0700338std::string HardwareComposer::Dump() {
339 std::unique_lock<std::mutex> lock(post_thread_mutex_);
340 std::ostringstream stream;
341
342 stream << "Display metrics: " << display_metrics_.width << "x"
343 << display_metrics_.height << " " << (display_metrics_.dpi.x / 1000.0)
344 << "x" << (display_metrics_.dpi.y / 1000.0) << " dpi @ "
345 << (1000000000.0 / display_metrics_.vsync_period_ns) << " Hz"
346 << std::endl;
347
348 stream << "Post thread resumed: " << post_thread_resumed_ << std::endl;
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700349 stream << "Active layers: " << layers_.size() << std::endl;
Corey Tabaka0b485c92017-05-19 12:02:58 -0700350 stream << std::endl;
351
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700352 for (size_t i = 0; i < layers_.size(); i++) {
Corey Tabaka0b485c92017-05-19 12:02:58 -0700353 stream << "Layer " << i << ":";
354 stream << " type=" << layers_[i].GetCompositionType().to_string();
355 stream << " surface_id=" << layers_[i].GetSurfaceId();
356 stream << " buffer_id=" << layers_[i].GetBufferId();
357 stream << std::endl;
358 }
359 stream << std::endl;
360
361 if (post_thread_resumed_) {
362 stream << "Hardware Composer Debug Info:" << std::endl;
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700363 stream << composer_->dumpDebugInfo();
Corey Tabaka0b485c92017-05-19 12:02:58 -0700364 }
365
366 return stream.str();
367}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800368
Corey Tabaka2251d822017-04-20 16:04:07 -0700369void HardwareComposer::PostLayers() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800370 ATRACE_NAME("HardwareComposer::PostLayers");
371
372 // Setup the hardware composer layers with current buffers.
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700373 for (auto& layer : layers_) {
374 layer.Prepare();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800375 }
376
Corey Tabaka2251d822017-04-20 16:04:07 -0700377 HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
378 if (error != HWC::Error::None) {
379 ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
380 error.to_string().c_str());
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700381 return;
382 }
383
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800384 // Now that we have taken in a frame from the application, we have a chance
385 // to drop the frame before passing the frame along to HWC.
386 // If the display driver has become backed up, we detect it here and then
387 // react by skipping this frame to catch up latency.
388 while (!retire_fence_fds_.empty() &&
389 (!retire_fence_fds_.front() ||
390 sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) {
391 // There are only 2 fences in here, no performance problem to shift the
392 // array of ints.
393 retire_fence_fds_.erase(retire_fence_fds_.begin());
394 }
395
396 const bool is_frame_pending = IsFramePendingInDriver();
George Burgess IV353a6f62017-06-26 17:13:09 -0700397 const bool is_fence_pending = static_cast<int32_t>(retire_fence_fds_.size()) >
John Bates954796e2017-05-11 11:00:31 -0700398 post_thread_config_.allowed_pending_fence_count;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800399
400 if (is_fence_pending || is_frame_pending) {
401 ATRACE_INT("frame_skip_count", ++frame_skip_count_);
402
403 ALOGW_IF(is_frame_pending, "Warning: frame already queued, dropping frame");
404 ALOGW_IF(is_fence_pending,
405 "Warning: dropping a frame to catch up with HWC (pending = %zd)",
406 retire_fence_fds_.size());
407
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700408 for (auto& layer : layers_) {
409 layer.Drop();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800410 }
411 return;
412 } else {
413 // Make the transition more obvious in systrace when the frame skip happens
414 // above.
415 ATRACE_INT("frame_skip_count", 0);
416 }
417
Corey Tabaka89bbefc2017-06-06 16:14:21 -0700418#if TRACE > 1
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700419 for (size_t i = 0; i < layers_.size(); i++) {
Corey Tabaka0b485c92017-05-19 12:02:58 -0700420 ALOGI("HardwareComposer::PostLayers: layer=%zu buffer_id=%d composition=%s",
421 i, layers_[i].GetBufferId(),
Corey Tabaka2251d822017-04-20 16:04:07 -0700422 layers_[i].GetCompositionType().to_string().c_str());
Corey Tabaka0b485c92017-05-19 12:02:58 -0700423 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800424#endif
425
Corey Tabaka2251d822017-04-20 16:04:07 -0700426 error = Present(HWC_DISPLAY_PRIMARY);
427 if (error != HWC::Error::None) {
428 ALOGE("HardwareComposer::PostLayers: Present failed: %s",
429 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800430 return;
431 }
432
433 std::vector<Hwc2::Layer> out_layers;
434 std::vector<int> out_fences;
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700435 error = composer_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
436 &out_fences);
Corey Tabaka2251d822017-04-20 16:04:07 -0700437 ALOGE_IF(error != HWC::Error::None,
438 "HardwareComposer::PostLayers: Failed to get release fences: %s",
439 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800440
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700441 // Perform post-frame bookkeeping.
Corey Tabaka2251d822017-04-20 16:04:07 -0700442 uint32_t num_elements = out_layers.size();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800443 for (size_t i = 0; i < num_elements; ++i) {
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700444 for (auto& layer : layers_) {
445 if (layer.GetLayerHandle() == out_layers[i]) {
446 layer.Finish(out_fences[i]);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800447 }
448 }
449 }
450}
451
Steven Thomas050b2c82017-03-06 11:45:16 -0800452void HardwareComposer::SetDisplaySurfaces(
Corey Tabaka2251d822017-04-20 16:04:07 -0700453 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
Jin Qian7480c062017-03-21 00:04:15 +0000454 ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
455 surfaces.size());
Corey Tabaka2251d822017-04-20 16:04:07 -0700456 const bool display_idle = surfaces.size() == 0;
457 {
458 std::unique_lock<std::mutex> lock(post_thread_mutex_);
459 pending_surfaces_ = std::move(surfaces);
460 }
461
Steven Thomas2ddf5672017-06-15 11:38:40 -0700462 if (request_display_callback_)
463 request_display_callback_(!display_idle);
464
Corey Tabaka2251d822017-04-20 16:04:07 -0700465 // Set idle state based on whether there are any surfaces to handle.
466 UpdatePostThreadState(PostThreadState::Idle, display_idle);
Steven Thomas050b2c82017-03-06 11:45:16 -0800467}
Jin Qian7480c062017-03-21 00:04:15 +0000468
John Bates954796e2017-05-11 11:00:31 -0700469int HardwareComposer::OnNewGlobalBuffer(DvrGlobalBufferKey key,
470 IonBuffer& ion_buffer) {
Okan Arikan822b7102017-05-08 13:31:34 -0700471 if (key == DvrGlobalBuffers::kVsyncBuffer) {
472 vsync_ring_ = std::make_unique<CPUMappedBroadcastRing<DvrVsyncRing>>(
473 &ion_buffer, CPUUsageMode::WRITE_OFTEN);
474
475 if (vsync_ring_->IsMapped() == false) {
476 return -EPERM;
477 }
478 }
479
480 if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
John Bates954796e2017-05-11 11:00:31 -0700481 return MapConfigBuffer(ion_buffer);
482 }
483
484 return 0;
485}
486
487void HardwareComposer::OnDeletedGlobalBuffer(DvrGlobalBufferKey key) {
Okan Arikan822b7102017-05-08 13:31:34 -0700488 if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
John Bates954796e2017-05-11 11:00:31 -0700489 ConfigBufferDeleted();
490 }
491}
492
493int HardwareComposer::MapConfigBuffer(IonBuffer& ion_buffer) {
494 std::lock_guard<std::mutex> lock(shared_config_mutex_);
Okan Arikan6f468c62017-05-31 14:48:30 -0700495 shared_config_ring_ = DvrConfigRing();
John Bates954796e2017-05-11 11:00:31 -0700496
Okan Arikan6f468c62017-05-31 14:48:30 -0700497 if (ion_buffer.width() < DvrConfigRing::MemorySize()) {
John Bates954796e2017-05-11 11:00:31 -0700498 ALOGE("HardwareComposer::MapConfigBuffer: invalid buffer size.");
499 return -EINVAL;
500 }
501
502 void* buffer_base = 0;
503 int result = ion_buffer.Lock(ion_buffer.usage(), 0, 0, ion_buffer.width(),
504 ion_buffer.height(), &buffer_base);
505 if (result != 0) {
Corey Tabaka0b485c92017-05-19 12:02:58 -0700506 ALOGE(
507 "HardwareComposer::MapConfigBuffer: Failed to map vrflinger config "
508 "buffer.");
John Bates954796e2017-05-11 11:00:31 -0700509 return -EPERM;
510 }
511
Okan Arikan6f468c62017-05-31 14:48:30 -0700512 shared_config_ring_ = DvrConfigRing::Create(buffer_base, ion_buffer.width());
John Bates954796e2017-05-11 11:00:31 -0700513 ion_buffer.Unlock();
514
515 return 0;
516}
517
518void HardwareComposer::ConfigBufferDeleted() {
519 std::lock_guard<std::mutex> lock(shared_config_mutex_);
Okan Arikan6f468c62017-05-31 14:48:30 -0700520 shared_config_ring_ = DvrConfigRing();
John Bates954796e2017-05-11 11:00:31 -0700521}
522
523void HardwareComposer::UpdateConfigBuffer() {
524 std::lock_guard<std::mutex> lock(shared_config_mutex_);
525 if (!shared_config_ring_.is_valid())
526 return;
527 // Copy from latest record in shared_config_ring_ to local copy.
Okan Arikan6f468c62017-05-31 14:48:30 -0700528 DvrConfig record;
John Bates954796e2017-05-11 11:00:31 -0700529 if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
530 post_thread_config_ = record;
531 }
532}
533
Corey Tabaka2251d822017-04-20 16:04:07 -0700534int HardwareComposer::PostThreadPollInterruptible(
Steven Thomasd7f49c52017-07-26 18:48:28 -0700535 const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) {
Steven Thomas050b2c82017-03-06 11:45:16 -0800536 pollfd pfd[2] = {
537 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700538 .fd = event_fd.Get(),
Steven Thomas66747c12017-03-22 18:45:31 -0700539 .events = static_cast<short>(requested_events),
540 .revents = 0,
Steven Thomas050b2c82017-03-06 11:45:16 -0800541 },
542 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700543 .fd = post_thread_event_fd_.Get(),
Steven Thomas050b2c82017-03-06 11:45:16 -0800544 .events = POLLPRI | POLLIN,
545 .revents = 0,
546 },
547 };
548 int ret, error;
549 do {
Steven Thomasd7f49c52017-07-26 18:48:28 -0700550 ret = poll(pfd, 2, timeout_ms);
Steven Thomas050b2c82017-03-06 11:45:16 -0800551 error = errno;
552 ALOGW_IF(ret < 0,
553 "HardwareComposer::PostThreadPollInterruptible: Error during "
554 "poll(): %s (%d)",
555 strerror(error), error);
556 } while (ret < 0 && error == EINTR);
557
558 if (ret < 0) {
559 return -error;
Steven Thomasd7f49c52017-07-26 18:48:28 -0700560 } else if (ret == 0) {
561 return -ETIMEDOUT;
Steven Thomas050b2c82017-03-06 11:45:16 -0800562 } else if (pfd[0].revents != 0) {
563 return 0;
564 } else if (pfd[1].revents != 0) {
565 ALOGI("VrHwcPost thread interrupted");
566 return kPostThreadInterrupted;
567 } else {
568 return 0;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800569 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800570}
571
572// Reads the value of the display driver wait_pingpong state. Returns 0 or 1
573// (the value of the state) on success or a negative error otherwise.
574// TODO(eieio): This is pretty driver specific, this should be moved to a
575// separate class eventually.
576int HardwareComposer::ReadWaitPPState() {
577 // Gracefully handle when the kernel does not support this feature.
578 if (!primary_display_wait_pp_fd_)
579 return 0;
580
581 const int wait_pp_fd = primary_display_wait_pp_fd_.Get();
582 int ret, error;
583
584 ret = lseek(wait_pp_fd, 0, SEEK_SET);
585 if (ret < 0) {
586 error = errno;
587 ALOGE("HardwareComposer::ReadWaitPPState: Failed to seek wait_pp fd: %s",
588 strerror(error));
589 return -error;
590 }
591
592 char data = -1;
593 ret = read(wait_pp_fd, &data, sizeof(data));
594 if (ret < 0) {
595 error = errno;
596 ALOGE("HardwareComposer::ReadWaitPPState: Failed to read wait_pp state: %s",
597 strerror(error));
598 return -error;
599 }
600
601 switch (data) {
602 case '0':
603 return 0;
604 case '1':
605 return 1;
606 default:
607 ALOGE(
608 "HardwareComposer::ReadWaitPPState: Unexpected value for wait_pp: %d",
609 data);
610 return -EINVAL;
611 }
612}
613
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800614// Waits for the next vsync and returns the timestamp of the vsync event. If
615// vsync already passed since the last call, returns the latest vsync timestamp
Steven Thomasd7f49c52017-07-26 18:48:28 -0700616// instead of blocking.
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800617int HardwareComposer::WaitForVSync(int64_t* timestamp) {
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700618 int error = PostThreadPollInterruptible(composer_callback_->GetVsyncEventFd(),
619 POLLIN, /*timeout_ms*/ 1000);
Steven Thomasd7f49c52017-07-26 18:48:28 -0700620 if (error == kPostThreadInterrupted || error < 0) {
621 return error;
622 } else {
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700623 *timestamp = composer_callback_->GetVsyncTime();
Steven Thomasd7f49c52017-07-26 18:48:28 -0700624 return 0;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800625 }
626}
627
628int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
629 const int timer_fd = vsync_sleep_timer_fd_.Get();
630 const itimerspec wakeup_itimerspec = {
631 .it_interval = {.tv_sec = 0, .tv_nsec = 0},
632 .it_value = NsToTimespec(wakeup_timestamp),
633 };
634 int ret =
635 timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr);
636 int error = errno;
637 if (ret < 0) {
638 ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s",
639 strerror(error));
640 return -error;
641 }
642
Steven Thomasd7f49c52017-07-26 18:48:28 -0700643 return PostThreadPollInterruptible(
644 vsync_sleep_timer_fd_, POLLIN, /*timeout_ms*/ -1);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800645}
646
647void HardwareComposer::PostThread() {
648 // NOLINTNEXTLINE(runtime/int)
Steven Thomas050b2c82017-03-06 11:45:16 -0800649 prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800650
Corey Tabaka2251d822017-04-20 16:04:07 -0700651 // Set the scheduler to SCHED_FIFO with high priority. If this fails here
652 // there may have been a startup timing issue between this thread and
653 // performanced. Try again later when this thread becomes active.
654 bool thread_policy_setup =
655 SetThreadPolicy("graphics:high", "/system/performance");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800656
Steven Thomas050b2c82017-03-06 11:45:16 -0800657#if ENABLE_BACKLIGHT_BRIGHTNESS
658 // TODO(hendrikw): This isn't required at the moment. It's possible that there
659 // is another method to access this when needed.
660 // Open the backlight brightness control sysfs node.
661 backlight_brightness_fd_ = LocalHandle(kBacklightBrightnessSysFile, O_RDWR);
662 ALOGW_IF(!backlight_brightness_fd_,
663 "HardwareComposer: Failed to open backlight brightness control: %s",
664 strerror(errno));
Corey Tabaka2251d822017-04-20 16:04:07 -0700665#endif // ENABLE_BACKLIGHT_BRIGHTNESS
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800666
Steven Thomas050b2c82017-03-06 11:45:16 -0800667 // Open the wait pingpong status node for the primary display.
668 // TODO(eieio): Move this into a platform-specific class.
669 primary_display_wait_pp_fd_ =
670 LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY);
671 ALOGW_IF(
672 !primary_display_wait_pp_fd_,
673 "HardwareComposer: Failed to open wait_pp node for primary display: %s",
674 strerror(errno));
675
676 // Create a timerfd based on CLOCK_MONOTINIC.
677 vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
678 LOG_ALWAYS_FATAL_IF(
679 !vsync_sleep_timer_fd_,
680 "HardwareComposer: Failed to create vsync sleep timerfd: %s",
681 strerror(errno));
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800682
683 const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
684 const int64_t photon_offset_ns = GetPosePredictionTimeOffset(ns_per_frame);
685
686 // TODO(jbates) Query vblank time from device, when such an API is available.
687 // This value (6.3%) was measured on A00 in low persistence mode.
688 int64_t vblank_ns = ns_per_frame * 63 / 1000;
689 int64_t right_eye_photon_offset_ns = (ns_per_frame - vblank_ns) / 2;
690
691 // Check property for overriding right eye offset value.
692 right_eye_photon_offset_ns =
693 property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
694
Steven Thomas050b2c82017-03-06 11:45:16 -0800695 bool was_running = false;
696
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800697 while (1) {
698 ATRACE_NAME("HardwareComposer::PostThread");
699
John Bates954796e2017-05-11 11:00:31 -0700700 // Check for updated config once per vsync.
701 UpdateConfigBuffer();
702
Corey Tabaka2251d822017-04-20 16:04:07 -0700703 while (post_thread_quiescent_) {
Steven Thomas050b2c82017-03-06 11:45:16 -0800704 std::unique_lock<std::mutex> lock(post_thread_mutex_);
Corey Tabaka2251d822017-04-20 16:04:07 -0700705 ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
706
Corey Tabakadf0b9162017-08-03 17:14:08 -0700707 // Tear down resources if necessary.
708 if (was_running)
709 OnPostThreadPaused();
Corey Tabaka2251d822017-04-20 16:04:07 -0700710
711 was_running = false;
712 post_thread_resumed_ = false;
713 post_thread_ready_.notify_all();
714
715 if (post_thread_state_ & PostThreadState::Quit) {
716 ALOGI("HardwareComposer::PostThread: Quitting.");
717 return;
Steven Thomas282a5ed2017-02-07 18:07:01 -0800718 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700719
720 post_thread_wait_.wait(lock, [this] { return !post_thread_quiescent_; });
721
722 post_thread_resumed_ = true;
723 post_thread_ready_.notify_all();
724
725 ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
Steven Thomas050b2c82017-03-06 11:45:16 -0800726 }
727
728 if (!was_running) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700729 // Setup resources.
Steven Thomas050b2c82017-03-06 11:45:16 -0800730 OnPostThreadResumed();
731 was_running = true;
Corey Tabaka2251d822017-04-20 16:04:07 -0700732
733 // Try to setup the scheduler policy if it failed during startup. Only
734 // attempt to do this on transitions from inactive to active to avoid
735 // spamming the system with RPCs and log messages.
736 if (!thread_policy_setup) {
737 thread_policy_setup =
738 SetThreadPolicy("graphics:high", "/system/performance");
739 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800740 }
741
742 int64_t vsync_timestamp = 0;
743 {
744 std::array<char, 128> buf;
745 snprintf(buf.data(), buf.size(), "wait_vsync|vsync=%d|",
746 vsync_count_ + 1);
747 ATRACE_NAME(buf.data());
748
Corey Tabaka2251d822017-04-20 16:04:07 -0700749 const int error = WaitForVSync(&vsync_timestamp);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800750 ALOGE_IF(
751 error < 0,
752 "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
753 strerror(-error));
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800754 // Don't bother processing this frame if a pause was requested
Steven Thomas050b2c82017-03-06 11:45:16 -0800755 if (error == kPostThreadInterrupted)
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800756 continue;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800757 }
758
759 ++vsync_count_;
760
Corey Tabaka2251d822017-04-20 16:04:07 -0700761 const bool layer_config_changed = UpdateLayerConfig();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800762
Okan Arikan822b7102017-05-08 13:31:34 -0700763 // Publish the vsync event.
764 if (vsync_ring_) {
765 DvrVsync vsync;
766 vsync.vsync_count = vsync_count_;
767 vsync.vsync_timestamp_ns = vsync_timestamp;
768 vsync.vsync_left_eye_offset_ns = photon_offset_ns;
769 vsync.vsync_right_eye_offset_ns = right_eye_photon_offset_ns;
770 vsync.vsync_period_ns = ns_per_frame;
771
772 vsync_ring_->Publish(vsync);
773 }
774
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800775 // Signal all of the vsync clients. Because absolute time is used for the
776 // wakeup time below, this can take a little time if necessary.
777 if (vsync_callback_)
Corey Tabaka2251d822017-04-20 16:04:07 -0700778 vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp,
779 /*frame_time_estimate*/ 0, vsync_count_);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800780
781 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700782 // Sleep until shortly before vsync.
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800783 ATRACE_NAME("sleep");
784
Corey Tabaka2251d822017-04-20 16:04:07 -0700785 const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
786 const int64_t now_ns = GetSystemClockNs();
John Bates954796e2017-05-11 11:00:31 -0700787 const int64_t sleep_time_ns = display_time_est_ns - now_ns -
788 post_thread_config_.frame_post_offset_ns;
789 const int64_t wakeup_time_ns =
790 display_time_est_ns - post_thread_config_.frame_post_offset_ns;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800791
792 ATRACE_INT64("sleep_time_ns", sleep_time_ns);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800793 if (sleep_time_ns > 0) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700794 int error = SleepUntil(wakeup_time_ns);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800795 ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s",
796 strerror(-error));
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700797 if (error == kPostThreadInterrupted) {
798 if (layer_config_changed) {
799 // If the layer config changed we need to validateDisplay() even if
800 // we're going to drop the frame, to flush the Composer object's
801 // internal command buffer and apply our layer changes.
802 Validate(HWC_DISPLAY_PRIMARY);
803 }
Steven Thomas050b2c82017-03-06 11:45:16 -0800804 continue;
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700805 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800806 }
807 }
808
Corey Tabaka2251d822017-04-20 16:04:07 -0700809 PostLayers();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800810 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800811}
812
Corey Tabaka2251d822017-04-20 16:04:07 -0700813// Checks for changes in the surface stack and updates the layer config to
814// accomodate the new stack.
Steven Thomas050b2c82017-03-06 11:45:16 -0800815bool HardwareComposer::UpdateLayerConfig() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700816 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
Steven Thomas050b2c82017-03-06 11:45:16 -0800817 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700818 std::unique_lock<std::mutex> lock(post_thread_mutex_);
819 if (pending_surfaces_.empty())
Steven Thomas050b2c82017-03-06 11:45:16 -0800820 return false;
Corey Tabaka2251d822017-04-20 16:04:07 -0700821
822 surfaces = std::move(pending_surfaces_);
Steven Thomas050b2c82017-03-06 11:45:16 -0800823 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800824
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800825 ATRACE_NAME("UpdateLayerConfig_HwLayers");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800826
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700827 // Sort the new direct surface list by z-order to determine the relative order
828 // of the surfaces. This relative order is used for the HWC z-order value to
829 // insulate VrFlinger and HWC z-order semantics from each other.
830 std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) {
831 return a->z_order() < b->z_order();
832 });
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800833
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700834 // Prepare a new layer stack, pulling in layers from the previous
835 // layer stack that are still active and updating their attributes.
836 std::vector<Layer> layers;
837 size_t layer_index = 0;
838 for (const auto& surface : surfaces) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700839 // The bottom layer is opaque, other layers blend.
840 HWC::BlendMode blending =
841 layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700842
843 // Try to find a layer for this surface in the set of active layers.
844 auto search =
845 std::lower_bound(layers_.begin(), layers_.end(), surface->surface_id());
846 const bool found = search != layers_.end() &&
847 search->GetSurfaceId() == surface->surface_id();
848 if (found) {
849 // Update the attributes of the layer that may have changed.
850 search->SetBlending(blending);
851 search->SetZOrder(layer_index); // Relative z-order.
852
853 // Move the existing layer to the new layer set and remove the empty layer
854 // object from the current set.
855 layers.push_back(std::move(*search));
856 layers_.erase(search);
857 } else {
858 // Insert a layer for the new surface.
859 layers.emplace_back(surface, blending, display_transform_,
860 HWC::Composition::Device, layer_index);
861 }
862
863 ALOGI_IF(
864 TRACE,
865 "HardwareComposer::UpdateLayerConfig: layer_index=%zu surface_id=%d",
866 layer_index, layers[layer_index].GetSurfaceId());
867
868 layer_index++;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800869 }
870
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700871 // Sort the new layer stack by ascending surface id.
872 std::sort(layers.begin(), layers.end());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800873
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700874 // Replace the previous layer set with the new layer set. The destructor of
875 // the previous set will clean up the remaining Layers that are not moved to
876 // the new layer set.
877 layers_ = std::move(layers);
878
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800879 ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700880 layers_.size());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800881 return true;
882}
883
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800884void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
885 vsync_callback_ = callback;
886}
887
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800888void HardwareComposer::SetBacklightBrightness(int brightness) {
889 if (backlight_brightness_fd_) {
890 std::array<char, 32> text;
891 const int length = snprintf(text.data(), text.size(), "%d", brightness);
892 write(backlight_brightness_fd_.Get(), text.data(), length);
893 }
894}
895
Steven Thomasd7f49c52017-07-26 18:48:28 -0700896HardwareComposer::ComposerCallback::ComposerCallback() {
897 vsync_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
898 LOG_ALWAYS_FATAL_IF(
899 !vsync_event_fd_,
900 "Failed to create vsync event fd : %s",
901 strerror(errno));
902}
903
904Return<void> HardwareComposer::ComposerCallback::onHotplug(
905 Hwc2::Display /*display*/,
906 IComposerCallback::Connection /*conn*/) {
907 return Void();
908}
909
910Return<void> HardwareComposer::ComposerCallback::onRefresh(
911 Hwc2::Display /*display*/) {
912 return hardware::Void();
913}
914
915Return<void> HardwareComposer::ComposerCallback::onVsync(
916 Hwc2::Display display, int64_t timestamp) {
917 if (display == HWC_DISPLAY_PRIMARY) {
918 std::lock_guard<std::mutex> lock(vsync_mutex_);
919 vsync_time_ = timestamp;
920 int error = eventfd_write(vsync_event_fd_.Get(), 1);
921 LOG_ALWAYS_FATAL_IF(error != 0, "Failed writing to vsync event fd");
922 }
923 return Void();
924}
925
926const pdx::LocalHandle&
927HardwareComposer::ComposerCallback::GetVsyncEventFd() const {
928 return vsync_event_fd_;
929}
930
931int64_t HardwareComposer::ComposerCallback::GetVsyncTime() {
932 std::lock_guard<std::mutex> lock(vsync_mutex_);
933 eventfd_t event;
934 eventfd_read(vsync_event_fd_.Get(), &event);
935 LOG_ALWAYS_FATAL_IF(vsync_time_ < 0,
936 "Attempt to read vsync time before vsync event");
937 int64_t return_val = vsync_time_;
938 vsync_time_ = -1;
939 return return_val;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800940}
941
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700942Hwc2::Composer* Layer::composer_{nullptr};
943HWCDisplayMetrics Layer::display_metrics_{0, 0, {0, 0}, 0};
944
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800945void Layer::Reset() {
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700946 if (hardware_composer_layer_) {
947 composer_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800948 hardware_composer_layer_ = 0;
949 }
950
Corey Tabaka2251d822017-04-20 16:04:07 -0700951 z_order_ = 0;
952 blending_ = HWC::BlendMode::None;
953 transform_ = HWC::Transform::None;
954 composition_type_ = HWC::Composition::Invalid;
955 target_composition_type_ = composition_type_;
956 source_ = EmptyVariant{};
957 acquire_fence_.Close();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800958 surface_rect_functions_applied_ = false;
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700959 pending_visibility_settings_ = true;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800960}
961
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700962Layer::Layer(const std::shared_ptr<DirectDisplaySurface>& surface,
963 HWC::BlendMode blending, HWC::Transform transform,
964 HWC::Composition composition_type, size_t z_order)
965 : z_order_{z_order},
966 blending_{blending},
967 transform_{transform},
968 target_composition_type_{composition_type},
969 source_{SourceSurface{surface}} {
970 CommonLayerSetup();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800971}
972
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700973Layer::Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
974 HWC::Transform transform, HWC::Composition composition_type,
975 size_t z_order)
976 : z_order_{z_order},
977 blending_{blending},
978 transform_{transform},
979 target_composition_type_{composition_type},
980 source_{SourceBuffer{buffer}} {
981 CommonLayerSetup();
982}
983
984Layer::~Layer() { Reset(); }
985
986Layer::Layer(Layer&& other) { *this = std::move(other); }
987
988Layer& Layer::operator=(Layer&& other) {
989 if (this != &other) {
990 Reset();
991 using std::swap;
992 swap(hardware_composer_layer_, other.hardware_composer_layer_);
993 swap(z_order_, other.z_order_);
994 swap(blending_, other.blending_);
995 swap(transform_, other.transform_);
996 swap(composition_type_, other.composition_type_);
997 swap(target_composition_type_, other.target_composition_type_);
998 swap(source_, other.source_);
999 swap(acquire_fence_, other.acquire_fence_);
1000 swap(surface_rect_functions_applied_,
1001 other.surface_rect_functions_applied_);
1002 swap(pending_visibility_settings_, other.pending_visibility_settings_);
1003 }
1004 return *this;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001005}
1006
Corey Tabaka2251d822017-04-20 16:04:07 -07001007void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
1008 if (source_.is<SourceBuffer>())
1009 std::get<SourceBuffer>(source_) = {buffer};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001010}
1011
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001012void Layer::SetBlending(HWC::BlendMode blending) {
1013 if (blending_ != blending) {
1014 blending_ = blending;
1015 pending_visibility_settings_ = true;
1016 }
1017}
1018
1019void Layer::SetZOrder(size_t z_order) {
1020 if (z_order_ != z_order) {
1021 z_order_ = z_order;
1022 pending_visibility_settings_ = true;
1023 }
1024}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001025
1026IonBuffer* Layer::GetBuffer() {
Corey Tabaka2251d822017-04-20 16:04:07 -07001027 struct Visitor {
1028 IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
1029 IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
1030 IonBuffer* operator()(EmptyVariant) { return nullptr; }
1031 };
1032 return source_.Visit(Visitor{});
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001033}
1034
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001035void Layer::UpdateVisibilitySettings() {
1036 if (pending_visibility_settings_) {
1037 pending_visibility_settings_ = false;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001038
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001039 HWC::Error error;
1040 hwc2_display_t display = HWC_DISPLAY_PRIMARY;
1041
1042 error = composer_->setLayerBlendMode(
1043 display, hardware_composer_layer_,
1044 blending_.cast<Hwc2::IComposerClient::BlendMode>());
1045 ALOGE_IF(error != HWC::Error::None,
1046 "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
1047 error.to_string().c_str());
1048
1049 error =
1050 composer_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
1051 ALOGE_IF(error != HWC::Error::None,
1052 "Layer::UpdateLayerSettings: Error setting z_ order: %s",
1053 error.to_string().c_str());
1054 }
1055}
1056
1057void Layer::UpdateLayerSettings() {
Corey Tabaka2251d822017-04-20 16:04:07 -07001058 HWC::Error error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001059 hwc2_display_t display = HWC_DISPLAY_PRIMARY;
1060
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001061 UpdateVisibilitySettings();
1062
Corey Tabaka2251d822017-04-20 16:04:07 -07001063 // TODO(eieio): Use surface attributes or some other mechanism to control
1064 // the layer display frame.
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001065 error = composer_->setLayerDisplayFrame(
Corey Tabaka2251d822017-04-20 16:04:07 -07001066 display, hardware_composer_layer_,
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001067 {0, 0, display_metrics_.width, display_metrics_.height});
Corey Tabaka2251d822017-04-20 16:04:07 -07001068 ALOGE_IF(error != HWC::Error::None,
1069 "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
1070 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001071
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001072 error = composer_->setLayerVisibleRegion(
Corey Tabaka2251d822017-04-20 16:04:07 -07001073 display, hardware_composer_layer_,
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001074 {{0, 0, display_metrics_.width, display_metrics_.height}});
Corey Tabaka2251d822017-04-20 16:04:07 -07001075 ALOGE_IF(error != HWC::Error::None,
1076 "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
1077 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001078
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001079 error =
1080 composer_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
Corey Tabaka2251d822017-04-20 16:04:07 -07001081 ALOGE_IF(error != HWC::Error::None,
1082 "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
1083 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001084}
1085
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001086void Layer::CommonLayerSetup() {
Corey Tabaka2251d822017-04-20 16:04:07 -07001087 HWC::Error error =
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001088 composer_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
1089 ALOGE_IF(error != HWC::Error::None,
1090 "Layer::CommonLayerSetup: Failed to create layer on primary "
1091 "display: %s",
1092 error.to_string().c_str());
1093 UpdateLayerSettings();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001094}
1095
1096void Layer::Prepare() {
1097 int right, bottom;
Daniel Nicoara1f42e3a2017-04-10 13:27:32 -04001098 sp<GraphicBuffer> handle;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001099
Corey Tabaka2251d822017-04-20 16:04:07 -07001100 // Acquire the next buffer according to the type of source.
1101 IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
1102 std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
1103 });
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001104
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001105 // Update any visibility (blending, z-order) changes that occurred since
1106 // last prepare.
1107 UpdateVisibilitySettings();
1108
1109 // When a layer is first setup there may be some time before the first
1110 // buffer arrives. Setup the HWC layer as a solid color to stall for time
1111 // until the first buffer arrives. Once the first buffer arrives there will
1112 // always be a buffer for the frame even if it is old.
Corey Tabaka2251d822017-04-20 16:04:07 -07001113 if (!handle.get()) {
1114 if (composition_type_ == HWC::Composition::Invalid) {
1115 composition_type_ = HWC::Composition::SolidColor;
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001116 composer_->setLayerCompositionType(
Corey Tabaka2251d822017-04-20 16:04:07 -07001117 HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1118 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1119 Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001120 composer_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1121 layer_color);
Corey Tabaka2251d822017-04-20 16:04:07 -07001122 } else {
1123 // The composition type is already set. Nothing else to do until a
1124 // buffer arrives.
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001125 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001126 } else {
Corey Tabaka2251d822017-04-20 16:04:07 -07001127 if (composition_type_ != target_composition_type_) {
1128 composition_type_ = target_composition_type_;
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001129 composer_->setLayerCompositionType(
Corey Tabaka2251d822017-04-20 16:04:07 -07001130 HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1131 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1132 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001133
Corey Tabaka2251d822017-04-20 16:04:07 -07001134 HWC::Error error{HWC::Error::None};
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001135 error =
1136 composer_->setLayerBuffer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1137 0, handle, acquire_fence_.Get());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001138
Corey Tabaka2251d822017-04-20 16:04:07 -07001139 ALOGE_IF(error != HWC::Error::None,
1140 "Layer::Prepare: Error setting layer buffer: %s",
1141 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001142
Corey Tabaka2251d822017-04-20 16:04:07 -07001143 if (!surface_rect_functions_applied_) {
1144 const float float_right = right;
1145 const float float_bottom = bottom;
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001146 error = composer_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
1147 hardware_composer_layer_,
1148 {0, 0, float_right, float_bottom});
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001149
Corey Tabaka2251d822017-04-20 16:04:07 -07001150 ALOGE_IF(error != HWC::Error::None,
1151 "Layer::Prepare: Error setting layer source crop: %s",
1152 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001153
Corey Tabaka2251d822017-04-20 16:04:07 -07001154 surface_rect_functions_applied_ = true;
1155 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001156 }
1157}
1158
1159void Layer::Finish(int release_fence_fd) {
Corey Tabaka2251d822017-04-20 16:04:07 -07001160 IfAnyOf<SourceSurface, SourceBuffer>::Call(
1161 &source_, [release_fence_fd](auto& source) {
1162 source.Finish(LocalHandle(release_fence_fd));
1163 });
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001164}
1165
Corey Tabaka2251d822017-04-20 16:04:07 -07001166void Layer::Drop() { acquire_fence_.Close(); }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001167
1168} // namespace dvr
1169} // namespace android