1 #include "hardware_composer.h"
2
3 #include <cutils/properties.h>
4 #include <cutils/sched_policy.h>
5 #include <fcntl.h>
6 #include <log/log.h>
7 #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>
14 #include <time.h>
15 #include <unistd.h>
16 #include <utils/Trace.h>
17
18 #include <algorithm>
19 #include <chrono>
20 #include <functional>
21 #include <map>
22
23 #include <dvr/dvr_display_types.h>
24 #include <dvr/performance_client_api.h>
25 #include <private/dvr/clock_ns.h>
26 #include <private/dvr/ion_buffer.h>
27 #include <private/dvr/pose_client_internal.h>
28
29 using android::pdx::LocalHandle;
30 using android::pdx::rpc::EmptyVariant;
31 using android::pdx::rpc::IfAnyOf;
32
33 using namespace std::chrono_literals;
34
35 namespace android {
36 namespace dvr {
37
38 namespace {
39
40 // If the number of pending fences goes over this count at the point when we
41 // are about to submit a new frame to HWC, we will drop the frame. This should
42 // be a signal that the display driver has begun queuing frames. Note that with
43 // smart displays (with RAM), the fence is signaled earlier than the next vsync,
44 // at the point when the DMA to the display completes. Currently we use a smart
45 // display and the EDS timing coincides with zero pending fences, so this is 0.
46 constexpr int kAllowedPendingFenceCount = 0;
47
48 // Offset before vsync to submit frames to hardware composer.
49 constexpr int64_t kFramePostOffsetNs = 4000000; // 4ms
50
51 const char kBacklightBrightnessSysFile[] =
52 "/sys/class/leds/lcd-backlight/brightness";
53
54 const char kPrimaryDisplayVSyncEventFile[] =
55 "/sys/class/graphics/fb0/vsync_event";
56
57 const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
58
59 const char kDvrPerformanceProperty[] = "sys.dvr.performance";
60
61 const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
62
63 // Get time offset from a vsync to when the pose for that vsync should be
64 // predicted out to. For example, if scanout gets halfway through the frame
65 // at the halfway point between vsyncs, then this could be half the period.
66 // With global shutter displays, this should be changed to the offset to when
67 // illumination begins. Low persistence adds a frame of latency, so we predict
68 // to the center of the next frame.
GetPosePredictionTimeOffset(int64_t vsync_period_ns)69 inline int64_t GetPosePredictionTimeOffset(int64_t vsync_period_ns) {
70 return (vsync_period_ns * 150) / 100;
71 }
72
73 // Attempts to set the scheduler class and partiton for the current thread.
74 // Returns true on success or false on failure.
SetThreadPolicy(const std::string & scheduler_class,const std::string & partition)75 bool SetThreadPolicy(const std::string& scheduler_class,
76 const std::string& partition) {
77 int error = dvrSetSchedulerClass(0, scheduler_class.c_str());
78 if (error < 0) {
79 ALOGE(
80 "SetThreadPolicy: Failed to set scheduler class \"%s\" for "
81 "thread_id=%d: %s",
82 scheduler_class.c_str(), gettid(), strerror(-error));
83 return false;
84 }
85 error = dvrSetCpuPartition(0, partition.c_str());
86 if (error < 0) {
87 ALOGE(
88 "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: "
89 "%s",
90 partition.c_str(), gettid(), strerror(-error));
91 return false;
92 }
93 return true;
94 }
95
96 } // anonymous namespace
97
98 // Layer static data.
99 Hwc2::Composer* Layer::hwc2_hidl_;
100 const HWCDisplayMetrics* Layer::display_metrics_;
101
102 // HardwareComposer static data;
103 constexpr size_t HardwareComposer::kMaxHardwareLayers;
104
HardwareComposer()105 HardwareComposer::HardwareComposer()
106 : HardwareComposer(nullptr, RequestDisplayCallback()) {}
107
HardwareComposer(Hwc2::Composer * hwc2_hidl,RequestDisplayCallback request_display_callback)108 HardwareComposer::HardwareComposer(
109 Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
110 : initialized_(false),
111 hwc2_hidl_(hwc2_hidl),
112 request_display_callback_(request_display_callback),
113 callbacks_(new ComposerCallback) {}
114
~HardwareComposer(void)115 HardwareComposer::~HardwareComposer(void) {
116 UpdatePostThreadState(PostThreadState::Quit, true);
117 if (post_thread_.joinable())
118 post_thread_.join();
119 }
120
Initialize()121 bool HardwareComposer::Initialize() {
122 if (initialized_) {
123 ALOGE("HardwareComposer::Initialize: already initialized.");
124 return false;
125 }
126
127 HWC::Error error = HWC::Error::None;
128
129 Hwc2::Config config;
130 error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
131
132 if (error != HWC::Error::None) {
133 ALOGE("HardwareComposer: Failed to get current display config : %d",
134 config);
135 return false;
136 }
137
138 error =
139 GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
140
141 if (error != HWC::Error::None) {
142 ALOGE(
143 "HardwareComposer: Failed to get display attributes for current "
144 "configuration : %d",
145 error.value);
146 return false;
147 }
148
149 ALOGI(
150 "HardwareComposer: primary display attributes: width=%d height=%d "
151 "vsync_period_ns=%d DPI=%dx%d",
152 native_display_metrics_.width, native_display_metrics_.height,
153 native_display_metrics_.vsync_period_ns, native_display_metrics_.dpi.x,
154 native_display_metrics_.dpi.y);
155
156 // Set the display metrics but never use rotation to avoid the long latency of
157 // rotation processing in hwc.
158 display_transform_ = HWC_TRANSFORM_NONE;
159 display_metrics_ = native_display_metrics_;
160
161 // Pass hwc instance and metrics to setup globals for Layer.
162 Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
163
164 post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
165 LOG_ALWAYS_FATAL_IF(
166 !post_thread_event_fd_,
167 "HardwareComposer: Failed to create interrupt event fd : %s",
168 strerror(errno));
169
170 post_thread_ = std::thread(&HardwareComposer::PostThread, this);
171
172 initialized_ = true;
173
174 return initialized_;
175 }
176
Enable()177 void HardwareComposer::Enable() {
178 UpdatePostThreadState(PostThreadState::Suspended, false);
179 }
180
Disable()181 void HardwareComposer::Disable() {
182 UpdatePostThreadState(PostThreadState::Suspended, true);
183 }
184
185 // Update the post thread quiescent state based on idle and suspended inputs.
UpdatePostThreadState(PostThreadStateType state,bool suspend)186 void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
187 bool suspend) {
188 std::unique_lock<std::mutex> lock(post_thread_mutex_);
189
190 // Update the votes in the state variable before evaluating the effective
191 // quiescent state. Any bits set in post_thread_state_ indicate that the post
192 // thread should be suspended.
193 if (suspend) {
194 post_thread_state_ |= state;
195 } else {
196 post_thread_state_ &= ~state;
197 }
198
199 const bool quit = post_thread_state_ & PostThreadState::Quit;
200 const bool effective_suspend = post_thread_state_ != PostThreadState::Active;
201 if (quit) {
202 post_thread_quiescent_ = true;
203 eventfd_write(post_thread_event_fd_.Get(), 1);
204 post_thread_wait_.notify_one();
205 } else if (effective_suspend && !post_thread_quiescent_) {
206 post_thread_quiescent_ = true;
207 eventfd_write(post_thread_event_fd_.Get(), 1);
208 } else if (!effective_suspend && post_thread_quiescent_) {
209 post_thread_quiescent_ = false;
210 eventfd_t value;
211 eventfd_read(post_thread_event_fd_.Get(), &value);
212 post_thread_wait_.notify_one();
213 }
214
215 // Wait until the post thread is in the requested state.
216 post_thread_ready_.wait(lock, [this, effective_suspend] {
217 return effective_suspend != post_thread_resumed_;
218 });
219 }
220
OnPostThreadResumed()221 void HardwareComposer::OnPostThreadResumed() {
222 hwc2_hidl_->resetCommands();
223
224 // Connect to pose service.
225 pose_client_ = dvrPoseCreate();
226 ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
227
228 // HIDL HWC seems to have an internal race condition. If we submit a frame too
229 // soon after turning on VSync we don't get any VSync signals. Give poor HWC
230 // implementations a chance to enable VSync before we continue.
231 EnableVsync(false);
232 std::this_thread::sleep_for(100ms);
233 EnableVsync(true);
234 std::this_thread::sleep_for(100ms);
235
236 // TODO(skiazyk): We need to do something about accessing this directly,
237 // supposedly there is a backlight service on the way.
238 // TODO(steventhomas): When we change the backlight setting, will surface
239 // flinger (or something else) set it back to its original value once we give
240 // control of the display back to surface flinger?
241 SetBacklightBrightness(255);
242
243 // Trigger target-specific performance mode change.
244 property_set(kDvrPerformanceProperty, "performance");
245 }
246
OnPostThreadPaused()247 void HardwareComposer::OnPostThreadPaused() {
248 retire_fence_fds_.clear();
249 display_surfaces_.clear();
250
251 for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
252 layers_[i].Reset();
253 }
254 active_layer_count_ = 0;
255
256 if (pose_client_) {
257 dvrPoseDestroy(pose_client_);
258 pose_client_ = nullptr;
259 }
260
261 EnableVsync(false);
262
263 hwc2_hidl_->resetCommands();
264
265 // Trigger target-specific performance mode change.
266 property_set(kDvrPerformanceProperty, "idle");
267 }
268
Validate(hwc2_display_t display)269 HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
270 uint32_t num_types;
271 uint32_t num_requests;
272 HWC::Error error =
273 hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
274
275 if (error == HWC2_ERROR_HAS_CHANGES) {
276 // TODO(skiazyk): We might need to inspect the requested changes first, but
277 // so far it seems like we shouldn't ever hit a bad state.
278 // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
279 // display);
280 error = hwc2_hidl_->acceptDisplayChanges(display);
281 }
282
283 return error;
284 }
285
EnableVsync(bool enabled)286 int32_t HardwareComposer::EnableVsync(bool enabled) {
287 return (int32_t)hwc2_hidl_->setVsyncEnabled(
288 HWC_DISPLAY_PRIMARY,
289 (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
290 : HWC2_VSYNC_DISABLE));
291 }
292
Present(hwc2_display_t display)293 HWC::Error HardwareComposer::Present(hwc2_display_t display) {
294 int32_t present_fence;
295 HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
296
297 // According to the documentation, this fence is signaled at the time of
298 // vsync/DMA for physical displays.
299 if (error == HWC::Error::None) {
300 ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
301 retire_fence_fds_.emplace_back(present_fence);
302 } else {
303 ATRACE_INT("HardwareComposer: PresentResult", error);
304 }
305
306 return error;
307 }
308
GetDisplayAttribute(hwc2_display_t display,hwc2_config_t config,hwc2_attribute_t attribute,int32_t * out_value) const309 HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
310 hwc2_config_t config,
311 hwc2_attribute_t attribute,
312 int32_t* out_value) const {
313 return hwc2_hidl_->getDisplayAttribute(
314 display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
315 }
316
GetDisplayMetrics(hwc2_display_t display,hwc2_config_t config,HWCDisplayMetrics * out_metrics) const317 HWC::Error HardwareComposer::GetDisplayMetrics(
318 hwc2_display_t display, hwc2_config_t config,
319 HWCDisplayMetrics* out_metrics) const {
320 HWC::Error error;
321
322 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
323 &out_metrics->width);
324 if (error != HWC::Error::None) {
325 ALOGE(
326 "HardwareComposer::GetDisplayMetrics: Failed to get display width: %s",
327 error.to_string().c_str());
328 return error;
329 }
330
331 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
332 &out_metrics->height);
333 if (error != HWC::Error::None) {
334 ALOGE(
335 "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
336 error.to_string().c_str());
337 return error;
338 }
339
340 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
341 &out_metrics->vsync_period_ns);
342 if (error != HWC::Error::None) {
343 ALOGE(
344 "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
345 error.to_string().c_str());
346 return error;
347 }
348
349 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
350 &out_metrics->dpi.x);
351 if (error != HWC::Error::None) {
352 ALOGE(
353 "HardwareComposer::GetDisplayMetrics: Failed to get display DPI X: %s",
354 error.to_string().c_str());
355 return error;
356 }
357
358 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
359 &out_metrics->dpi.y);
360 if (error != HWC::Error::None) {
361 ALOGE(
362 "HardwareComposer::GetDisplayMetrics: Failed to get display DPI Y: %s",
363 error.to_string().c_str());
364 return error;
365 }
366
367 return HWC::Error::None;
368 }
369
Dump()370 std::string HardwareComposer::Dump() { return hwc2_hidl_->dumpDebugInfo(); }
371
PostLayers()372 void HardwareComposer::PostLayers() {
373 ATRACE_NAME("HardwareComposer::PostLayers");
374
375 // Setup the hardware composer layers with current buffers.
376 for (size_t i = 0; i < active_layer_count_; i++) {
377 layers_[i].Prepare();
378 }
379
380 HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
381 if (error != HWC::Error::None) {
382 ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
383 error.to_string().c_str());
384 return;
385 }
386
387 // Now that we have taken in a frame from the application, we have a chance
388 // to drop the frame before passing the frame along to HWC.
389 // If the display driver has become backed up, we detect it here and then
390 // react by skipping this frame to catch up latency.
391 while (!retire_fence_fds_.empty() &&
392 (!retire_fence_fds_.front() ||
393 sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) {
394 // There are only 2 fences in here, no performance problem to shift the
395 // array of ints.
396 retire_fence_fds_.erase(retire_fence_fds_.begin());
397 }
398
399 const bool is_frame_pending = IsFramePendingInDriver();
400 const bool is_fence_pending =
401 retire_fence_fds_.size() > kAllowedPendingFenceCount;
402
403 if (is_fence_pending || is_frame_pending) {
404 ATRACE_INT("frame_skip_count", ++frame_skip_count_);
405
406 ALOGW_IF(is_frame_pending, "Warning: frame already queued, dropping frame");
407 ALOGW_IF(is_fence_pending,
408 "Warning: dropping a frame to catch up with HWC (pending = %zd)",
409 retire_fence_fds_.size());
410
411 for (size_t i = 0; i < active_layer_count_; i++) {
412 layers_[i].Drop();
413 }
414 return;
415 } else {
416 // Make the transition more obvious in systrace when the frame skip happens
417 // above.
418 ATRACE_INT("frame_skip_count", 0);
419 }
420
421 #if TRACE
422 for (size_t i = 0; i < active_layer_count_; i++)
423 ALOGI("HardwareComposer::PostLayers: layer=%zu composition=%s", i,
424 layers_[i].GetCompositionType().to_string().c_str());
425 #endif
426
427 error = Present(HWC_DISPLAY_PRIMARY);
428 if (error != HWC::Error::None) {
429 ALOGE("HardwareComposer::PostLayers: Present failed: %s",
430 error.to_string().c_str());
431 return;
432 }
433
434 std::vector<Hwc2::Layer> out_layers;
435 std::vector<int> out_fences;
436 error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
437 &out_fences);
438 ALOGE_IF(error != HWC::Error::None,
439 "HardwareComposer::PostLayers: Failed to get release fences: %s",
440 error.to_string().c_str());
441
442 // Perform post-frame bookkeeping. Unused layers are a no-op.
443 uint32_t num_elements = out_layers.size();
444 for (size_t i = 0; i < num_elements; ++i) {
445 for (size_t j = 0; j < active_layer_count_; ++j) {
446 if (layers_[j].GetLayerHandle() == out_layers[i]) {
447 layers_[j].Finish(out_fences[i]);
448 }
449 }
450 }
451 }
452
SetDisplaySurfaces(std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces)453 void HardwareComposer::SetDisplaySurfaces(
454 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
455 ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
456 surfaces.size());
457 const bool display_idle = surfaces.size() == 0;
458 {
459 std::unique_lock<std::mutex> lock(post_thread_mutex_);
460 pending_surfaces_ = std::move(surfaces);
461 }
462
463 // Set idle state based on whether there are any surfaces to handle.
464 UpdatePostThreadState(PostThreadState::Idle, display_idle);
465
466 // XXX: TEMPORARY
467 // Request control of the display based on whether there are any surfaces to
468 // handle. This callback sets the post thread active state once the transition
469 // is complete in SurfaceFlinger.
470 // TODO(eieio): Unify the control signal used to move SurfaceFlinger into VR
471 // mode. Currently this is hooked up to persistent VR mode, but perhaps this
472 // makes more sense to control it from VrCore, which could in turn base its
473 // decision on persistent VR mode.
474 if (request_display_callback_)
475 request_display_callback_(!display_idle);
476 }
477
PostThreadPollInterruptible(const pdx::LocalHandle & event_fd,int requested_events)478 int HardwareComposer::PostThreadPollInterruptible(
479 const pdx::LocalHandle& event_fd, int requested_events) {
480 pollfd pfd[2] = {
481 {
482 .fd = event_fd.Get(),
483 .events = static_cast<short>(requested_events),
484 .revents = 0,
485 },
486 {
487 .fd = post_thread_event_fd_.Get(),
488 .events = POLLPRI | POLLIN,
489 .revents = 0,
490 },
491 };
492 int ret, error;
493 do {
494 ret = poll(pfd, 2, -1);
495 error = errno;
496 ALOGW_IF(ret < 0,
497 "HardwareComposer::PostThreadPollInterruptible: Error during "
498 "poll(): %s (%d)",
499 strerror(error), error);
500 } while (ret < 0 && error == EINTR);
501
502 if (ret < 0) {
503 return -error;
504 } else if (pfd[0].revents != 0) {
505 return 0;
506 } else if (pfd[1].revents != 0) {
507 ALOGI("VrHwcPost thread interrupted");
508 return kPostThreadInterrupted;
509 } else {
510 return 0;
511 }
512 }
513
514 // Reads the value of the display driver wait_pingpong state. Returns 0 or 1
515 // (the value of the state) on success or a negative error otherwise.
516 // TODO(eieio): This is pretty driver specific, this should be moved to a
517 // separate class eventually.
ReadWaitPPState()518 int HardwareComposer::ReadWaitPPState() {
519 // Gracefully handle when the kernel does not support this feature.
520 if (!primary_display_wait_pp_fd_)
521 return 0;
522
523 const int wait_pp_fd = primary_display_wait_pp_fd_.Get();
524 int ret, error;
525
526 ret = lseek(wait_pp_fd, 0, SEEK_SET);
527 if (ret < 0) {
528 error = errno;
529 ALOGE("HardwareComposer::ReadWaitPPState: Failed to seek wait_pp fd: %s",
530 strerror(error));
531 return -error;
532 }
533
534 char data = -1;
535 ret = read(wait_pp_fd, &data, sizeof(data));
536 if (ret < 0) {
537 error = errno;
538 ALOGE("HardwareComposer::ReadWaitPPState: Failed to read wait_pp state: %s",
539 strerror(error));
540 return -error;
541 }
542
543 switch (data) {
544 case '0':
545 return 0;
546 case '1':
547 return 1;
548 default:
549 ALOGE(
550 "HardwareComposer::ReadWaitPPState: Unexpected value for wait_pp: %d",
551 data);
552 return -EINVAL;
553 }
554 }
555
556 // Reads the timestamp of the last vsync from the display driver.
557 // TODO(eieio): This is pretty driver specific, this should be moved to a
558 // separate class eventually.
ReadVSyncTimestamp(int64_t * timestamp)559 int HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) {
560 const int event_fd = primary_display_vsync_event_fd_.Get();
561 int ret, error;
562
563 // The driver returns data in the form "VSYNC=<timestamp ns>".
564 std::array<char, 32> data;
565 data.fill('\0');
566
567 // Seek back to the beginning of the event file.
568 ret = lseek(event_fd, 0, SEEK_SET);
569 if (ret < 0) {
570 error = errno;
571 ALOGE(
572 "HardwareComposer::ReadVSyncTimestamp: Failed to seek vsync event fd: "
573 "%s",
574 strerror(error));
575 return -error;
576 }
577
578 // Read the vsync event timestamp.
579 ret = read(event_fd, data.data(), data.size());
580 if (ret < 0) {
581 error = errno;
582 ALOGE_IF(
583 error != EAGAIN,
584 "HardwareComposer::ReadVSyncTimestamp: Error while reading timestamp: "
585 "%s",
586 strerror(error));
587 return -error;
588 }
589
590 ret = sscanf(data.data(), "VSYNC=%" PRIu64,
591 reinterpret_cast<uint64_t*>(timestamp));
592 if (ret < 0) {
593 error = errno;
594 ALOGE(
595 "HardwareComposer::ReadVSyncTimestamp: Error while parsing timestamp: "
596 "%s",
597 strerror(error));
598 return -error;
599 }
600
601 return 0;
602 }
603
604 // Blocks until the next vsync event is signaled by the display driver.
605 // TODO(eieio): This is pretty driver specific, this should be moved to a
606 // separate class eventually.
BlockUntilVSync()607 int HardwareComposer::BlockUntilVSync() {
608 // Vsync is signaled by POLLPRI on the fb vsync node.
609 return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
610 }
611
612 // Waits for the next vsync and returns the timestamp of the vsync event. If
613 // vsync already passed since the last call, returns the latest vsync timestamp
614 // instead of blocking. This method updates the last_vsync_timeout_ in the
615 // process.
616 //
617 // TODO(eieio): This is pretty driver specific, this should be moved to a
618 // separate class eventually.
WaitForVSync(int64_t * timestamp)619 int HardwareComposer::WaitForVSync(int64_t* timestamp) {
620 int error;
621
622 // Get the current timestamp and decide what to do.
623 while (true) {
624 int64_t current_vsync_timestamp;
625 error = ReadVSyncTimestamp(¤t_vsync_timestamp);
626 if (error < 0 && error != -EAGAIN)
627 return error;
628
629 if (error == -EAGAIN) {
630 // Vsync was turned off, wait for the next vsync event.
631 error = BlockUntilVSync();
632 if (error < 0 || error == kPostThreadInterrupted)
633 return error;
634
635 // Try again to get the timestamp for this new vsync interval.
636 continue;
637 }
638
639 // Check that we advanced to a later vsync interval.
640 if (TimestampGT(current_vsync_timestamp, last_vsync_timestamp_)) {
641 *timestamp = last_vsync_timestamp_ = current_vsync_timestamp;
642 return 0;
643 }
644
645 // See how close we are to the next expected vsync. If we're within 1ms,
646 // sleep for 1ms and try again.
647 const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
648 const int64_t threshold_ns = 1000000; // 1ms
649
650 const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
651 const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
652
653 if (distance_to_vsync_est > threshold_ns) {
654 // Wait for vsync event notification.
655 error = BlockUntilVSync();
656 if (error < 0 || error == kPostThreadInterrupted)
657 return error;
658 } else {
659 // Sleep for a short time (1 millisecond) before retrying.
660 error = SleepUntil(GetSystemClockNs() + threshold_ns);
661 if (error < 0 || error == kPostThreadInterrupted)
662 return error;
663 }
664 }
665 }
666
SleepUntil(int64_t wakeup_timestamp)667 int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
668 const int timer_fd = vsync_sleep_timer_fd_.Get();
669 const itimerspec wakeup_itimerspec = {
670 .it_interval = {.tv_sec = 0, .tv_nsec = 0},
671 .it_value = NsToTimespec(wakeup_timestamp),
672 };
673 int ret =
674 timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr);
675 int error = errno;
676 if (ret < 0) {
677 ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s",
678 strerror(error));
679 return -error;
680 }
681
682 return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
683 }
684
PostThread()685 void HardwareComposer::PostThread() {
686 // NOLINTNEXTLINE(runtime/int)
687 prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
688
689 // Set the scheduler to SCHED_FIFO with high priority. If this fails here
690 // there may have been a startup timing issue between this thread and
691 // performanced. Try again later when this thread becomes active.
692 bool thread_policy_setup =
693 SetThreadPolicy("graphics:high", "/system/performance");
694
695 #if ENABLE_BACKLIGHT_BRIGHTNESS
696 // TODO(hendrikw): This isn't required at the moment. It's possible that there
697 // is another method to access this when needed.
698 // Open the backlight brightness control sysfs node.
699 backlight_brightness_fd_ = LocalHandle(kBacklightBrightnessSysFile, O_RDWR);
700 ALOGW_IF(!backlight_brightness_fd_,
701 "HardwareComposer: Failed to open backlight brightness control: %s",
702 strerror(errno));
703 #endif // ENABLE_BACKLIGHT_BRIGHTNESS
704
705 // Open the vsync event node for the primary display.
706 // TODO(eieio): Move this into a platform-specific class.
707 primary_display_vsync_event_fd_ =
708 LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY);
709 ALOGE_IF(!primary_display_vsync_event_fd_,
710 "HardwareComposer: Failed to open vsync event node for primary "
711 "display: %s",
712 strerror(errno));
713
714 // Open the wait pingpong status node for the primary display.
715 // TODO(eieio): Move this into a platform-specific class.
716 primary_display_wait_pp_fd_ =
717 LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY);
718 ALOGW_IF(
719 !primary_display_wait_pp_fd_,
720 "HardwareComposer: Failed to open wait_pp node for primary display: %s",
721 strerror(errno));
722
723 // Create a timerfd based on CLOCK_MONOTINIC.
724 vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
725 LOG_ALWAYS_FATAL_IF(
726 !vsync_sleep_timer_fd_,
727 "HardwareComposer: Failed to create vsync sleep timerfd: %s",
728 strerror(errno));
729
730 const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
731 const int64_t photon_offset_ns = GetPosePredictionTimeOffset(ns_per_frame);
732
733 // TODO(jbates) Query vblank time from device, when such an API is available.
734 // This value (6.3%) was measured on A00 in low persistence mode.
735 int64_t vblank_ns = ns_per_frame * 63 / 1000;
736 int64_t right_eye_photon_offset_ns = (ns_per_frame - vblank_ns) / 2;
737
738 // Check property for overriding right eye offset value.
739 right_eye_photon_offset_ns =
740 property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
741
742 bool was_running = false;
743
744 while (1) {
745 ATRACE_NAME("HardwareComposer::PostThread");
746
747 while (post_thread_quiescent_) {
748 std::unique_lock<std::mutex> lock(post_thread_mutex_);
749 ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
750
751 // Tear down resources.
752 OnPostThreadPaused();
753
754 was_running = false;
755 post_thread_resumed_ = false;
756 post_thread_ready_.notify_all();
757
758 if (post_thread_state_ & PostThreadState::Quit) {
759 ALOGI("HardwareComposer::PostThread: Quitting.");
760 return;
761 }
762
763 post_thread_wait_.wait(lock, [this] { return !post_thread_quiescent_; });
764
765 post_thread_resumed_ = true;
766 post_thread_ready_.notify_all();
767
768 ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
769 }
770
771 if (!was_running) {
772 // Setup resources.
773 OnPostThreadResumed();
774 was_running = true;
775
776 // Try to setup the scheduler policy if it failed during startup. Only
777 // attempt to do this on transitions from inactive to active to avoid
778 // spamming the system with RPCs and log messages.
779 if (!thread_policy_setup) {
780 thread_policy_setup =
781 SetThreadPolicy("graphics:high", "/system/performance");
782 }
783 }
784
785 int64_t vsync_timestamp = 0;
786 {
787 std::array<char, 128> buf;
788 snprintf(buf.data(), buf.size(), "wait_vsync|vsync=%d|",
789 vsync_count_ + 1);
790 ATRACE_NAME(buf.data());
791
792 const int error = WaitForVSync(&vsync_timestamp);
793 ALOGE_IF(
794 error < 0,
795 "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
796 strerror(-error));
797 // Don't bother processing this frame if a pause was requested
798 if (error == kPostThreadInterrupted)
799 continue;
800 }
801
802 ++vsync_count_;
803
804 if (pose_client_) {
805 // Signal the pose service with vsync info.
806 // Display timestamp is in the middle of scanout.
807 privateDvrPoseNotifyVsync(pose_client_, vsync_count_,
808 vsync_timestamp + photon_offset_ns,
809 ns_per_frame, right_eye_photon_offset_ns);
810 }
811
812 const bool layer_config_changed = UpdateLayerConfig();
813
814 // Signal all of the vsync clients. Because absolute time is used for the
815 // wakeup time below, this can take a little time if necessary.
816 if (vsync_callback_)
817 vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp,
818 /*frame_time_estimate*/ 0, vsync_count_);
819
820 {
821 // Sleep until shortly before vsync.
822 ATRACE_NAME("sleep");
823
824 const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
825 const int64_t now_ns = GetSystemClockNs();
826 const int64_t sleep_time_ns =
827 display_time_est_ns - now_ns - kFramePostOffsetNs;
828 const int64_t wakeup_time_ns = display_time_est_ns - kFramePostOffsetNs;
829
830 ATRACE_INT64("sleep_time_ns", sleep_time_ns);
831 if (sleep_time_ns > 0) {
832 int error = SleepUntil(wakeup_time_ns);
833 ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s",
834 strerror(-error));
835 if (error == kPostThreadInterrupted) {
836 if (layer_config_changed) {
837 // If the layer config changed we need to validateDisplay() even if
838 // we're going to drop the frame, to flush the Composer object's
839 // internal command buffer and apply our layer changes.
840 Validate(HWC_DISPLAY_PRIMARY);
841 }
842 continue;
843 }
844 }
845 }
846
847 PostLayers();
848 }
849 }
850
851 // Checks for changes in the surface stack and updates the layer config to
852 // accomodate the new stack.
UpdateLayerConfig()853 bool HardwareComposer::UpdateLayerConfig() {
854 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
855 {
856 std::unique_lock<std::mutex> lock(post_thread_mutex_);
857 if (pending_surfaces_.empty())
858 return false;
859
860 surfaces = std::move(pending_surfaces_);
861 }
862
863 ATRACE_NAME("UpdateLayerConfig_HwLayers");
864
865 display_surfaces_.clear();
866
867 Layer* target_layer;
868 size_t layer_index;
869 for (layer_index = 0;
870 layer_index < std::min(surfaces.size(), kMaxHardwareLayers);
871 layer_index++) {
872 // The bottom layer is opaque, other layers blend.
873 HWC::BlendMode blending =
874 layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
875 layers_[layer_index].Setup(surfaces[layer_index], blending,
876 display_transform_, HWC::Composition::Device,
877 layer_index);
878 display_surfaces_.push_back(surfaces[layer_index]);
879 }
880
881 // Clear unused layers.
882 for (size_t i = layer_index; i < kMaxHardwareLayers; i++)
883 layers_[i].Reset();
884
885 active_layer_count_ = layer_index;
886 ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
887 active_layer_count_);
888
889 // Any surfaces left over could not be assigned a hardware layer and will
890 // not be displayed.
891 ALOGW_IF(surfaces.size() != display_surfaces_.size(),
892 "HardwareComposer::UpdateLayerConfig: More surfaces than layers: "
893 "pending_surfaces=%zu display_surfaces=%zu",
894 surfaces.size(), display_surfaces_.size());
895
896 return true;
897 }
898
SetVSyncCallback(VSyncCallback callback)899 void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
900 vsync_callback_ = callback;
901 }
902
HwcRefresh(hwc2_callback_data_t,hwc2_display_t)903 void HardwareComposer::HwcRefresh(hwc2_callback_data_t /*data*/,
904 hwc2_display_t /*display*/) {
905 // TODO(eieio): implement invalidate callbacks.
906 }
907
HwcVSync(hwc2_callback_data_t,hwc2_display_t,int64_t)908 void HardwareComposer::HwcVSync(hwc2_callback_data_t /*data*/,
909 hwc2_display_t /*display*/,
910 int64_t /*timestamp*/) {
911 ATRACE_NAME(__PRETTY_FUNCTION__);
912 // Intentionally empty. HWC may require a callback to be set to enable vsync
913 // signals. We bypass this callback thread by monitoring the vsync event
914 // directly, but signals still need to be enabled.
915 }
916
HwcHotplug(hwc2_callback_data_t,hwc2_display_t,hwc2_connection_t)917 void HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/,
918 hwc2_display_t /*display*/,
919 hwc2_connection_t /*connected*/) {
920 // TODO(eieio): implement display hotplug callbacks.
921 }
922
OnHardwareComposerRefresh()923 void HardwareComposer::OnHardwareComposerRefresh() {
924 // TODO(steventhomas): Handle refresh.
925 }
926
SetBacklightBrightness(int brightness)927 void HardwareComposer::SetBacklightBrightness(int brightness) {
928 if (backlight_brightness_fd_) {
929 std::array<char, 32> text;
930 const int length = snprintf(text.data(), text.size(), "%d", brightness);
931 write(backlight_brightness_fd_.Get(), text.data(), length);
932 }
933 }
934
InitializeGlobals(Hwc2::Composer * hwc2_hidl,const HWCDisplayMetrics * metrics)935 void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
936 const HWCDisplayMetrics* metrics) {
937 hwc2_hidl_ = hwc2_hidl;
938 display_metrics_ = metrics;
939 }
940
Reset()941 void Layer::Reset() {
942 if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
943 hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
944 hardware_composer_layer_ = 0;
945 }
946
947 z_order_ = 0;
948 blending_ = HWC::BlendMode::None;
949 transform_ = HWC::Transform::None;
950 composition_type_ = HWC::Composition::Invalid;
951 target_composition_type_ = composition_type_;
952 source_ = EmptyVariant{};
953 acquire_fence_.Close();
954 surface_rect_functions_applied_ = false;
955 }
956
Setup(const std::shared_ptr<DirectDisplaySurface> & surface,HWC::BlendMode blending,HWC::Transform transform,HWC::Composition composition_type,size_t z_order)957 void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
958 HWC::BlendMode blending, HWC::Transform transform,
959 HWC::Composition composition_type, size_t z_order) {
960 Reset();
961 z_order_ = z_order;
962 blending_ = blending;
963 transform_ = transform;
964 composition_type_ = HWC::Composition::Invalid;
965 target_composition_type_ = composition_type;
966 source_ = SourceSurface{surface};
967 CommonLayerSetup();
968 }
969
Setup(const std::shared_ptr<IonBuffer> & buffer,HWC::BlendMode blending,HWC::Transform transform,HWC::Composition composition_type,size_t z_order)970 void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
971 HWC::BlendMode blending, HWC::Transform transform,
972 HWC::Composition composition_type, size_t z_order) {
973 Reset();
974 z_order_ = z_order;
975 blending_ = blending;
976 transform_ = transform;
977 composition_type_ = HWC::Composition::Invalid;
978 target_composition_type_ = composition_type;
979 source_ = SourceBuffer{buffer};
980 CommonLayerSetup();
981 }
982
UpdateBuffer(const std::shared_ptr<IonBuffer> & buffer)983 void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
984 if (source_.is<SourceBuffer>())
985 std::get<SourceBuffer>(source_) = {buffer};
986 }
987
SetBlending(HWC::BlendMode blending)988 void Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; }
SetZOrder(size_t z_order)989 void Layer::SetZOrder(size_t z_order) { z_order_ = z_order; }
990
GetBuffer()991 IonBuffer* Layer::GetBuffer() {
992 struct Visitor {
993 IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
994 IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
995 IonBuffer* operator()(EmptyVariant) { return nullptr; }
996 };
997 return source_.Visit(Visitor{});
998 }
999
UpdateLayerSettings()1000 void Layer::UpdateLayerSettings() {
1001 if (!IsLayerSetup()) {
1002 ALOGE(
1003 "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
1004 "unused Layer!");
1005 return;
1006 }
1007
1008 HWC::Error error;
1009 hwc2_display_t display = HWC_DISPLAY_PRIMARY;
1010
1011 error = hwc2_hidl_->setLayerCompositionType(
1012 display, hardware_composer_layer_,
1013 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1014 ALOGE_IF(
1015 error != HWC::Error::None,
1016 "Layer::UpdateLayerSettings: Error setting layer composition type: %s",
1017 error.to_string().c_str());
1018
1019 error = hwc2_hidl_->setLayerBlendMode(
1020 display, hardware_composer_layer_,
1021 blending_.cast<Hwc2::IComposerClient::BlendMode>());
1022 ALOGE_IF(error != HWC::Error::None,
1023 "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
1024 error.to_string().c_str());
1025
1026 // TODO(eieio): Use surface attributes or some other mechanism to control
1027 // the layer display frame.
1028 error = hwc2_hidl_->setLayerDisplayFrame(
1029 display, hardware_composer_layer_,
1030 {0, 0, display_metrics_->width, display_metrics_->height});
1031 ALOGE_IF(error != HWC::Error::None,
1032 "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
1033 error.to_string().c_str());
1034
1035 error = hwc2_hidl_->setLayerVisibleRegion(
1036 display, hardware_composer_layer_,
1037 {{0, 0, display_metrics_->width, display_metrics_->height}});
1038 ALOGE_IF(error != HWC::Error::None,
1039 "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
1040 error.to_string().c_str());
1041
1042 error =
1043 hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
1044 ALOGE_IF(error != HWC::Error::None,
1045 "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
1046 error.to_string().c_str());
1047
1048 error =
1049 hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
1050 ALOGE_IF(error != HWC::Error::None,
1051 "Layer::UpdateLayerSettings: Error setting z_ order: %s",
1052 error.to_string().c_str());
1053 }
1054
CommonLayerSetup()1055 void Layer::CommonLayerSetup() {
1056 HWC::Error error =
1057 hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
1058 ALOGE_IF(
1059 error != HWC::Error::None,
1060 "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
1061 error.to_string().c_str());
1062 UpdateLayerSettings();
1063 }
1064
Prepare()1065 void Layer::Prepare() {
1066 int right, bottom;
1067 sp<GraphicBuffer> handle;
1068
1069 // Acquire the next buffer according to the type of source.
1070 IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
1071 std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
1072 });
1073
1074 // When a layer is first setup there may be some time before the first buffer
1075 // arrives. Setup the HWC layer as a solid color to stall for time until the
1076 // first buffer arrives. Once the first buffer arrives there will always be a
1077 // buffer for the frame even if it is old.
1078 if (!handle.get()) {
1079 if (composition_type_ == HWC::Composition::Invalid) {
1080 composition_type_ = HWC::Composition::SolidColor;
1081 hwc2_hidl_->setLayerCompositionType(
1082 HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1083 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1084 Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
1085 hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1086 layer_color);
1087 } else {
1088 // The composition type is already set. Nothing else to do until a
1089 // buffer arrives.
1090 }
1091 } else {
1092 if (composition_type_ != target_composition_type_) {
1093 composition_type_ = target_composition_type_;
1094 hwc2_hidl_->setLayerCompositionType(
1095 HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1096 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1097 }
1098
1099 HWC::Error error{HWC::Error::None};
1100 error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
1101 hardware_composer_layer_, 0, handle,
1102 acquire_fence_.Get());
1103
1104 ALOGE_IF(error != HWC::Error::None,
1105 "Layer::Prepare: Error setting layer buffer: %s",
1106 error.to_string().c_str());
1107
1108 if (!surface_rect_functions_applied_) {
1109 const float float_right = right;
1110 const float float_bottom = bottom;
1111 error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
1112 hardware_composer_layer_,
1113 {0, 0, float_right, float_bottom});
1114
1115 ALOGE_IF(error != HWC::Error::None,
1116 "Layer::Prepare: Error setting layer source crop: %s",
1117 error.to_string().c_str());
1118
1119 surface_rect_functions_applied_ = true;
1120 }
1121 }
1122 }
1123
Finish(int release_fence_fd)1124 void Layer::Finish(int release_fence_fd) {
1125 IfAnyOf<SourceSurface, SourceBuffer>::Call(
1126 &source_, [release_fence_fd](auto& source) {
1127 source.Finish(LocalHandle(release_fence_fd));
1128 });
1129 }
1130
Drop()1131 void Layer::Drop() { acquire_fence_.Close(); }
1132
1133 } // namespace dvr
1134 } // namespace android
1135