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 <stdint.h>
9 #include <sync/sync.h>
10 #include <sys/eventfd.h>
11 #include <sys/prctl.h>
12 #include <sys/resource.h>
13 #include <sys/system_properties.h>
14 #include <sys/timerfd.h>
15 #include <sys/types.h>
16 #include <time.h>
17 #include <unistd.h>
18 #include <utils/Trace.h>
19
20 #include <algorithm>
21 #include <chrono>
22 #include <functional>
23 #include <map>
24 #include <sstream>
25 #include <string>
26 #include <tuple>
27
28 #include <dvr/dvr_display_types.h>
29 #include <dvr/performance_client_api.h>
30 #include <private/dvr/clock_ns.h>
31 #include <private/dvr/ion_buffer.h>
32
33 using android::hardware::Return;
34 using android::hardware::Void;
35 using android::pdx::ErrorStatus;
36 using android::pdx::LocalHandle;
37 using android::pdx::Status;
38 using android::pdx::rpc::EmptyVariant;
39 using android::pdx::rpc::IfAnyOf;
40
41 using namespace std::chrono_literals;
42
43 namespace android {
44 namespace dvr {
45
46 namespace {
47
48 const char kDvrPerformanceProperty[] = "sys.dvr.performance";
49 const char kDvrStandaloneProperty[] = "ro.boot.vr";
50
51 const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
52
53 const char kUseExternalDisplayProperty[] = "persist.vr.use_external_display";
54
55 // How long to wait after boot finishes before we turn the display off.
56 constexpr int kBootFinishedDisplayOffTimeoutSec = 10;
57
58 constexpr int kDefaultDisplayWidth = 1920;
59 constexpr int kDefaultDisplayHeight = 1080;
60 constexpr int64_t kDefaultVsyncPeriodNs = 16666667;
61 // Hardware composer reports dpi as dots per thousand inches (dpi * 1000).
62 constexpr int kDefaultDpi = 400000;
63
64 // Get time offset from a vsync to when the pose for that vsync should be
65 // predicted out to. For example, if scanout gets halfway through the frame
66 // at the halfway point between vsyncs, then this could be half the period.
67 // With global shutter displays, this should be changed to the offset to when
68 // illumination begins. Low persistence adds a frame of latency, so we predict
69 // to the center of the next frame.
GetPosePredictionTimeOffset(int64_t vsync_period_ns)70 inline int64_t GetPosePredictionTimeOffset(int64_t vsync_period_ns) {
71 return (vsync_period_ns * 150) / 100;
72 }
73
74 // Attempts to set the scheduler class and partiton for the current thread.
75 // Returns true on success or false on failure.
SetThreadPolicy(const std::string & scheduler_class,const std::string & partition)76 bool SetThreadPolicy(const std::string& scheduler_class,
77 const std::string& partition) {
78 int error = dvrSetSchedulerClass(0, scheduler_class.c_str());
79 if (error < 0) {
80 ALOGE(
81 "SetThreadPolicy: Failed to set scheduler class \"%s\" for "
82 "thread_id=%d: %s",
83 scheduler_class.c_str(), gettid(), strerror(-error));
84 return false;
85 }
86 error = dvrSetCpuPartition(0, partition.c_str());
87 if (error < 0) {
88 ALOGE(
89 "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: "
90 "%s",
91 partition.c_str(), gettid(), strerror(-error));
92 return false;
93 }
94 return true;
95 }
96
97 // Utility to generate scoped tracers with arguments.
98 // TODO(eieio): Move/merge this into utils/Trace.h?
99 class TraceArgs {
100 public:
101 template <typename... Args>
TraceArgs(const char * format,Args &&...args)102 TraceArgs(const char* format, Args&&... args) {
103 std::array<char, 1024> buffer;
104 snprintf(buffer.data(), buffer.size(), format, std::forward<Args>(args)...);
105 atrace_begin(ATRACE_TAG, buffer.data());
106 }
107
~TraceArgs()108 ~TraceArgs() { atrace_end(ATRACE_TAG); }
109
110 private:
111 TraceArgs(const TraceArgs&) = delete;
112 void operator=(const TraceArgs&) = delete;
113 };
114
115 // Macro to define a scoped tracer with arguments. Uses PASTE(x, y) macro
116 // defined in utils/Trace.h.
117 #define TRACE_FORMAT(format, ...) \
118 TraceArgs PASTE(__tracer, __LINE__) { format, ##__VA_ARGS__ }
119
120 // Returns "primary" or "external". Useful for writing more readable logs.
GetDisplayName(bool is_primary)121 const char* GetDisplayName(bool is_primary) {
122 return is_primary ? "primary" : "external";
123 }
124
125 } // anonymous namespace
126
HardwareComposer()127 HardwareComposer::HardwareComposer()
128 : initialized_(false), request_display_callback_(nullptr) {}
129
~HardwareComposer(void)130 HardwareComposer::~HardwareComposer(void) {
131 UpdatePostThreadState(PostThreadState::Quit, true);
132 if (post_thread_.joinable())
133 post_thread_.join();
134 }
135
Initialize(Hwc2::Composer * composer,hwc2_display_t primary_display_id,RequestDisplayCallback request_display_callback)136 bool HardwareComposer::Initialize(
137 Hwc2::Composer* composer, hwc2_display_t primary_display_id,
138 RequestDisplayCallback request_display_callback) {
139 if (initialized_) {
140 ALOGE("HardwareComposer::Initialize: already initialized.");
141 return false;
142 }
143
144 is_standalone_device_ = property_get_bool(kDvrStandaloneProperty, false);
145
146 request_display_callback_ = request_display_callback;
147
148 primary_display_ = GetDisplayParams(composer, primary_display_id, true);
149
150 post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
151 LOG_ALWAYS_FATAL_IF(
152 !post_thread_event_fd_,
153 "HardwareComposer: Failed to create interrupt event fd : %s",
154 strerror(errno));
155
156 post_thread_ = std::thread(&HardwareComposer::PostThread, this);
157
158 initialized_ = true;
159
160 return initialized_;
161 }
162
Enable()163 void HardwareComposer::Enable() {
164 UpdatePostThreadState(PostThreadState::Suspended, false);
165 }
166
Disable()167 void HardwareComposer::Disable() {
168 UpdatePostThreadState(PostThreadState::Suspended, true);
169
170 std::unique_lock<std::mutex> lock(post_thread_mutex_);
171 post_thread_ready_.wait(lock, [this] {
172 return !post_thread_resumed_;
173 });
174 }
175
OnBootFinished()176 void HardwareComposer::OnBootFinished() {
177 std::lock_guard<std::mutex> lock(post_thread_mutex_);
178 if (boot_finished_)
179 return;
180 boot_finished_ = true;
181 post_thread_wait_.notify_one();
182 if (is_standalone_device_)
183 request_display_callback_(true);
184 }
185
186 // Update the post thread quiescent state based on idle and suspended inputs.
UpdatePostThreadState(PostThreadStateType state,bool suspend)187 void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
188 bool suspend) {
189 std::unique_lock<std::mutex> lock(post_thread_mutex_);
190
191 // Update the votes in the state variable before evaluating the effective
192 // quiescent state. Any bits set in post_thread_state_ indicate that the post
193 // thread should be suspended.
194 if (suspend) {
195 post_thread_state_ |= state;
196 } else {
197 post_thread_state_ &= ~state;
198 }
199
200 const bool quit = post_thread_state_ & PostThreadState::Quit;
201 const bool effective_suspend = post_thread_state_ != PostThreadState::Active;
202 if (quit) {
203 post_thread_quiescent_ = true;
204 eventfd_write(post_thread_event_fd_.Get(), 1);
205 post_thread_wait_.notify_one();
206 } else if (effective_suspend && !post_thread_quiescent_) {
207 post_thread_quiescent_ = true;
208 eventfd_write(post_thread_event_fd_.Get(), 1);
209 } else if (!effective_suspend && post_thread_quiescent_) {
210 post_thread_quiescent_ = false;
211 eventfd_t value;
212 eventfd_read(post_thread_event_fd_.Get(), &value);
213 post_thread_wait_.notify_one();
214 }
215 }
216
CreateComposer()217 void HardwareComposer::CreateComposer() {
218 if (composer_)
219 return;
220 composer_.reset(new Hwc2::impl::Composer("default"));
221 composer_callback_ = new ComposerCallback;
222 composer_->registerCallback(composer_callback_);
223 LOG_ALWAYS_FATAL_IF(!composer_callback_->GotFirstHotplug(),
224 "Registered composer callback but didn't get hotplug for primary"
225 " display");
226 }
227
OnPostThreadResumed()228 void HardwareComposer::OnPostThreadResumed() {
229 ALOGI("OnPostThreadResumed");
230 EnableDisplay(*target_display_, true);
231
232 // Trigger target-specific performance mode change.
233 property_set(kDvrPerformanceProperty, "performance");
234 }
235
OnPostThreadPaused()236 void HardwareComposer::OnPostThreadPaused() {
237 ALOGI("OnPostThreadPaused");
238 retire_fence_fds_.clear();
239 layers_.clear();
240
241 // Phones create a new composer client on resume and destroy it on pause.
242 // Standalones only create the composer client once and then use SetPowerMode
243 // to control the screen on pause/resume.
244 if (!is_standalone_device_) {
245 composer_callback_ = nullptr;
246 composer_.reset(nullptr);
247 } else {
248 EnableDisplay(*target_display_, false);
249 }
250
251 // Trigger target-specific performance mode change.
252 property_set(kDvrPerformanceProperty, "idle");
253 }
254
PostThreadCondWait(std::unique_lock<std::mutex> & lock,int timeout_sec,const std::function<bool ()> & pred)255 bool HardwareComposer::PostThreadCondWait(std::unique_lock<std::mutex>& lock,
256 int timeout_sec,
257 const std::function<bool()>& pred) {
258 auto pred_with_quit = [&] {
259 return pred() || (post_thread_state_ & PostThreadState::Quit);
260 };
261 if (timeout_sec >= 0) {
262 post_thread_wait_.wait_for(lock, std::chrono::seconds(timeout_sec),
263 pred_with_quit);
264 } else {
265 post_thread_wait_.wait(lock, pred_with_quit);
266 }
267 if (post_thread_state_ & PostThreadState::Quit) {
268 ALOGI("HardwareComposer::PostThread: Quitting.");
269 return true;
270 }
271 return false;
272 }
273
Validate(hwc2_display_t display)274 HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
275 uint32_t num_types;
276 uint32_t num_requests;
277 HWC::Error error =
278 composer_->validateDisplay(display, &num_types, &num_requests);
279
280 if (error == HWC2_ERROR_HAS_CHANGES) {
281 ALOGE("Hardware composer has requested composition changes, "
282 "which we don't support.");
283 // Accept the changes anyway and see if we can get something on the screen.
284 error = composer_->acceptDisplayChanges(display);
285 }
286
287 return error;
288 }
289
EnableVsync(const DisplayParams & display,bool enabled)290 bool HardwareComposer::EnableVsync(const DisplayParams& display, bool enabled) {
291 HWC::Error error = composer_->setVsyncEnabled(display.id,
292 (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
293 : HWC2_VSYNC_DISABLE));
294 if (error != HWC::Error::None) {
295 ALOGE("Error attempting to %s vsync on %s display: %s",
296 enabled ? "enable" : "disable", GetDisplayName(display.is_primary),
297 error.to_string().c_str());
298 }
299 return error == HWC::Error::None;
300 }
301
SetPowerMode(const DisplayParams & display,bool active)302 bool HardwareComposer::SetPowerMode(const DisplayParams& display, bool active) {
303 ALOGI("Turning %s display %s", GetDisplayName(display.is_primary),
304 active ? "on" : "off");
305 HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off;
306 HWC::Error error = composer_->setPowerMode(display.id,
307 power_mode.cast<Hwc2::IComposerClient::PowerMode>());
308 if (error != HWC::Error::None) {
309 ALOGE("Error attempting to turn %s display %s: %s",
310 GetDisplayName(display.is_primary), active ? "on" : "off",
311 error.to_string().c_str());
312 }
313 return error == HWC::Error::None;
314 }
315
EnableDisplay(const DisplayParams & display,bool enabled)316 bool HardwareComposer::EnableDisplay(const DisplayParams& display,
317 bool enabled) {
318 bool power_result;
319 bool vsync_result;
320 // When turning a display on, we set the power state then set vsync. When
321 // turning a display off we do it in the opposite order.
322 if (enabled) {
323 power_result = SetPowerMode(display, enabled);
324 vsync_result = EnableVsync(display, enabled);
325 } else {
326 vsync_result = EnableVsync(display, enabled);
327 power_result = SetPowerMode(display, enabled);
328 }
329 return power_result && vsync_result;
330 }
331
Present(hwc2_display_t display)332 HWC::Error HardwareComposer::Present(hwc2_display_t display) {
333 int32_t present_fence;
334 HWC::Error error = composer_->presentDisplay(display, &present_fence);
335
336 // According to the documentation, this fence is signaled at the time of
337 // vsync/DMA for physical displays.
338 if (error == HWC::Error::None) {
339 ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
340 retire_fence_fds_.emplace_back(present_fence);
341 } else {
342 ATRACE_INT("HardwareComposer: PresentResult", error);
343 }
344
345 return error;
346 }
347
GetDisplayParams(Hwc2::Composer * composer,hwc2_display_t display,bool is_primary)348 DisplayParams HardwareComposer::GetDisplayParams(
349 Hwc2::Composer* composer, hwc2_display_t display, bool is_primary) {
350 DisplayParams params;
351 params.id = display;
352 params.is_primary = is_primary;
353
354 Hwc2::Config config;
355 HWC::Error error = composer->getActiveConfig(display, &config);
356
357 if (error == HWC::Error::None) {
358 auto get_attr = [&](hwc2_attribute_t attr, const char* attr_name)
359 -> std::optional<int32_t> {
360 int32_t val;
361 HWC::Error error = composer->getDisplayAttribute(
362 display, config, (Hwc2::IComposerClient::Attribute)attr, &val);
363 if (error != HWC::Error::None) {
364 ALOGE("Failed to get %s display attr %s: %s",
365 GetDisplayName(is_primary), attr_name,
366 error.to_string().c_str());
367 return std::nullopt;
368 }
369 return val;
370 };
371
372 auto width = get_attr(HWC2_ATTRIBUTE_WIDTH, "width");
373 auto height = get_attr(HWC2_ATTRIBUTE_HEIGHT, "height");
374
375 if (width && height) {
376 params.width = *width;
377 params.height = *height;
378 } else {
379 ALOGI("Failed to get width and/or height for %s display. Using default"
380 " size %dx%d.", GetDisplayName(is_primary), kDefaultDisplayWidth,
381 kDefaultDisplayHeight);
382 params.width = kDefaultDisplayWidth;
383 params.height = kDefaultDisplayHeight;
384 }
385
386 auto vsync_period = get_attr(HWC2_ATTRIBUTE_VSYNC_PERIOD, "vsync period");
387 if (vsync_period) {
388 params.vsync_period_ns = *vsync_period;
389 } else {
390 ALOGI("Failed to get vsync period for %s display. Using default vsync"
391 " period %.2fms", GetDisplayName(is_primary),
392 static_cast<float>(kDefaultVsyncPeriodNs) / 1000000);
393 params.vsync_period_ns = kDefaultVsyncPeriodNs;
394 }
395
396 auto dpi_x = get_attr(HWC2_ATTRIBUTE_DPI_X, "DPI X");
397 auto dpi_y = get_attr(HWC2_ATTRIBUTE_DPI_Y, "DPI Y");
398 if (dpi_x && dpi_y) {
399 params.dpi.x = *dpi_x;
400 params.dpi.y = *dpi_y;
401 } else {
402 ALOGI("Failed to get dpi_x and/or dpi_y for %s display. Using default"
403 " dpi %d.", GetDisplayName(is_primary), kDefaultDpi);
404 params.dpi.x = kDefaultDpi;
405 params.dpi.y = kDefaultDpi;
406 }
407 } else {
408 ALOGE("HardwareComposer: Failed to get current %s display config: %d."
409 " Using default display values.",
410 GetDisplayName(is_primary), error.value);
411 params.width = kDefaultDisplayWidth;
412 params.height = kDefaultDisplayHeight;
413 params.dpi.x = kDefaultDpi;
414 params.dpi.y = kDefaultDpi;
415 params.vsync_period_ns = kDefaultVsyncPeriodNs;
416 }
417
418 ALOGI(
419 "HardwareComposer: %s display attributes: width=%d height=%d "
420 "vsync_period_ns=%d DPI=%dx%d",
421 GetDisplayName(is_primary),
422 params.width,
423 params.height,
424 params.vsync_period_ns,
425 params.dpi.x,
426 params.dpi.y);
427
428 return params;
429 }
430
Dump()431 std::string HardwareComposer::Dump() {
432 std::unique_lock<std::mutex> lock(post_thread_mutex_);
433 std::ostringstream stream;
434
435 auto print_display_metrics = [&](const DisplayParams& params) {
436 stream << GetDisplayName(params.is_primary)
437 << " display metrics: " << params.width << "x"
438 << params.height << " " << (params.dpi.x / 1000.0)
439 << "x" << (params.dpi.y / 1000.0) << " dpi @ "
440 << (1000000000.0 / params.vsync_period_ns) << " Hz"
441 << std::endl;
442 };
443
444 print_display_metrics(primary_display_);
445 if (external_display_)
446 print_display_metrics(*external_display_);
447
448 stream << "Post thread resumed: " << post_thread_resumed_ << std::endl;
449 stream << "Active layers: " << layers_.size() << std::endl;
450 stream << std::endl;
451
452 for (size_t i = 0; i < layers_.size(); i++) {
453 stream << "Layer " << i << ":";
454 stream << " type=" << layers_[i].GetCompositionType().to_string();
455 stream << " surface_id=" << layers_[i].GetSurfaceId();
456 stream << " buffer_id=" << layers_[i].GetBufferId();
457 stream << std::endl;
458 }
459 stream << std::endl;
460
461 if (post_thread_resumed_) {
462 stream << "Hardware Composer Debug Info:" << std::endl;
463 stream << composer_->dumpDebugInfo();
464 }
465
466 return stream.str();
467 }
468
PostLayers(hwc2_display_t display)469 void HardwareComposer::PostLayers(hwc2_display_t display) {
470 ATRACE_NAME("HardwareComposer::PostLayers");
471
472 // Setup the hardware composer layers with current buffers.
473 for (auto& layer : layers_) {
474 layer.Prepare();
475 }
476
477 // Now that we have taken in a frame from the application, we have a chance
478 // to drop the frame before passing the frame along to HWC.
479 // If the display driver has become backed up, we detect it here and then
480 // react by skipping this frame to catch up latency.
481 while (!retire_fence_fds_.empty() &&
482 (!retire_fence_fds_.front() ||
483 sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) {
484 // There are only 2 fences in here, no performance problem to shift the
485 // array of ints.
486 retire_fence_fds_.erase(retire_fence_fds_.begin());
487 }
488
489 const bool is_fence_pending = static_cast<int32_t>(retire_fence_fds_.size()) >
490 post_thread_config_.allowed_pending_fence_count;
491
492 if (is_fence_pending) {
493 ATRACE_INT("frame_skip_count", ++frame_skip_count_);
494
495 ALOGW_IF(is_fence_pending,
496 "Warning: dropping a frame to catch up with HWC (pending = %zd)",
497 retire_fence_fds_.size());
498
499 for (auto& layer : layers_) {
500 layer.Drop();
501 }
502 return;
503 } else {
504 // Make the transition more obvious in systrace when the frame skip happens
505 // above.
506 ATRACE_INT("frame_skip_count", 0);
507 }
508
509 #if TRACE > 1
510 for (size_t i = 0; i < layers_.size(); i++) {
511 ALOGI("HardwareComposer::PostLayers: layer=%zu buffer_id=%d composition=%s",
512 i, layers_[i].GetBufferId(),
513 layers_[i].GetCompositionType().to_string().c_str());
514 }
515 #endif
516
517 HWC::Error error = Validate(display);
518 if (error != HWC::Error::None) {
519 ALOGE("HardwareComposer::PostLayers: Validate failed: %s display=%" PRIu64,
520 error.to_string().c_str(), display);
521 return;
522 }
523
524 error = Present(display);
525 if (error != HWC::Error::None) {
526 ALOGE("HardwareComposer::PostLayers: Present failed: %s",
527 error.to_string().c_str());
528 return;
529 }
530
531 std::vector<Hwc2::Layer> out_layers;
532 std::vector<int> out_fences;
533 error = composer_->getReleaseFences(display,
534 &out_layers, &out_fences);
535 ALOGE_IF(error != HWC::Error::None,
536 "HardwareComposer::PostLayers: Failed to get release fences: %s",
537 error.to_string().c_str());
538
539 // Perform post-frame bookkeeping.
540 uint32_t num_elements = out_layers.size();
541 for (size_t i = 0; i < num_elements; ++i) {
542 for (auto& layer : layers_) {
543 if (layer.GetLayerHandle() == out_layers[i]) {
544 layer.Finish(out_fences[i]);
545 }
546 }
547 }
548 }
549
SetDisplaySurfaces(std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces)550 void HardwareComposer::SetDisplaySurfaces(
551 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
552 ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
553 surfaces.size());
554 const bool display_idle = surfaces.size() == 0;
555 {
556 std::unique_lock<std::mutex> lock(post_thread_mutex_);
557 surfaces_ = std::move(surfaces);
558 surfaces_changed_ = true;
559 }
560
561 if (request_display_callback_ && !is_standalone_device_)
562 request_display_callback_(!display_idle);
563
564 // Set idle state based on whether there are any surfaces to handle.
565 UpdatePostThreadState(PostThreadState::Idle, display_idle);
566 }
567
OnNewGlobalBuffer(DvrGlobalBufferKey key,IonBuffer & ion_buffer)568 int HardwareComposer::OnNewGlobalBuffer(DvrGlobalBufferKey key,
569 IonBuffer& ion_buffer) {
570 if (key == DvrGlobalBuffers::kVsyncBuffer) {
571 vsync_ring_ = std::make_unique<CPUMappedBroadcastRing<DvrVsyncRing>>(
572 &ion_buffer, CPUUsageMode::WRITE_OFTEN);
573
574 if (vsync_ring_->IsMapped() == false) {
575 return -EPERM;
576 }
577 }
578
579 if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
580 return MapConfigBuffer(ion_buffer);
581 }
582
583 return 0;
584 }
585
OnDeletedGlobalBuffer(DvrGlobalBufferKey key)586 void HardwareComposer::OnDeletedGlobalBuffer(DvrGlobalBufferKey key) {
587 if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
588 ConfigBufferDeleted();
589 }
590 }
591
MapConfigBuffer(IonBuffer & ion_buffer)592 int HardwareComposer::MapConfigBuffer(IonBuffer& ion_buffer) {
593 std::lock_guard<std::mutex> lock(shared_config_mutex_);
594 shared_config_ring_ = DvrConfigRing();
595
596 if (ion_buffer.width() < DvrConfigRing::MemorySize()) {
597 ALOGE("HardwareComposer::MapConfigBuffer: invalid buffer size.");
598 return -EINVAL;
599 }
600
601 void* buffer_base = 0;
602 int result = ion_buffer.Lock(ion_buffer.usage(), 0, 0, ion_buffer.width(),
603 ion_buffer.height(), &buffer_base);
604 if (result != 0) {
605 ALOGE(
606 "HardwareComposer::MapConfigBuffer: Failed to map vrflinger config "
607 "buffer.");
608 return -EPERM;
609 }
610
611 shared_config_ring_ = DvrConfigRing::Create(buffer_base, ion_buffer.width());
612 ion_buffer.Unlock();
613
614 return 0;
615 }
616
ConfigBufferDeleted()617 void HardwareComposer::ConfigBufferDeleted() {
618 std::lock_guard<std::mutex> lock(shared_config_mutex_);
619 shared_config_ring_ = DvrConfigRing();
620 }
621
UpdateConfigBuffer()622 void HardwareComposer::UpdateConfigBuffer() {
623 std::lock_guard<std::mutex> lock(shared_config_mutex_);
624 if (!shared_config_ring_.is_valid())
625 return;
626 // Copy from latest record in shared_config_ring_ to local copy.
627 DvrConfig record;
628 if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
629 ALOGI("DvrConfig updated: sequence %u, post offset %d",
630 shared_config_ring_sequence_, record.frame_post_offset_ns);
631 ++shared_config_ring_sequence_;
632 post_thread_config_ = record;
633 }
634 }
635
PostThreadPollInterruptible(const pdx::LocalHandle & event_fd,int requested_events,int timeout_ms)636 int HardwareComposer::PostThreadPollInterruptible(
637 const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) {
638 pollfd pfd[2] = {
639 {
640 .fd = event_fd.Get(),
641 .events = static_cast<short>(requested_events),
642 .revents = 0,
643 },
644 {
645 .fd = post_thread_event_fd_.Get(),
646 .events = POLLPRI | POLLIN,
647 .revents = 0,
648 },
649 };
650 int ret, error;
651 do {
652 ret = poll(pfd, 2, timeout_ms);
653 error = errno;
654 ALOGW_IF(ret < 0,
655 "HardwareComposer::PostThreadPollInterruptible: Error during "
656 "poll(): %s (%d)",
657 strerror(error), error);
658 } while (ret < 0 && error == EINTR);
659
660 if (ret < 0) {
661 return -error;
662 } else if (ret == 0) {
663 return -ETIMEDOUT;
664 } else if (pfd[0].revents != 0) {
665 return 0;
666 } else if (pfd[1].revents != 0) {
667 ALOGI("VrHwcPost thread interrupted: revents=%x", pfd[1].revents);
668 return kPostThreadInterrupted;
669 } else {
670 return 0;
671 }
672 }
673
674 // Sleep until the next predicted vsync, returning the predicted vsync
675 // timestamp.
WaitForPredictedVSync()676 Status<int64_t> HardwareComposer::WaitForPredictedVSync() {
677 const int64_t predicted_vsync_time = last_vsync_timestamp_ +
678 (target_display_->vsync_period_ns * vsync_prediction_interval_);
679 const int error = SleepUntil(predicted_vsync_time);
680 if (error < 0) {
681 ALOGE("HardwareComposer::WaifForVSync:: Failed to sleep: %s",
682 strerror(-error));
683 return error;
684 }
685 return {predicted_vsync_time};
686 }
687
SleepUntil(int64_t wakeup_timestamp)688 int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
689 const int timer_fd = vsync_sleep_timer_fd_.Get();
690 const itimerspec wakeup_itimerspec = {
691 .it_interval = {.tv_sec = 0, .tv_nsec = 0},
692 .it_value = NsToTimespec(wakeup_timestamp),
693 };
694 int ret =
695 timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr);
696 int error = errno;
697 if (ret < 0) {
698 ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s",
699 strerror(error));
700 return -error;
701 }
702
703 return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN,
704 /*timeout_ms*/ -1);
705 }
706
PostThread()707 void HardwareComposer::PostThread() {
708 // NOLINTNEXTLINE(runtime/int)
709 prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
710
711 // Set the scheduler to SCHED_FIFO with high priority. If this fails here
712 // there may have been a startup timing issue between this thread and
713 // performanced. Try again later when this thread becomes active.
714 bool thread_policy_setup =
715 SetThreadPolicy("graphics:high", "/system/performance");
716
717 // Create a timerfd based on CLOCK_MONOTINIC.
718 vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
719 LOG_ALWAYS_FATAL_IF(
720 !vsync_sleep_timer_fd_,
721 "HardwareComposer: Failed to create vsync sleep timerfd: %s",
722 strerror(errno));
723
724 struct VsyncEyeOffsets { int64_t left_ns, right_ns; };
725 bool was_running = false;
726
727 auto get_vsync_eye_offsets = [this]() -> VsyncEyeOffsets {
728 VsyncEyeOffsets offsets;
729 offsets.left_ns =
730 GetPosePredictionTimeOffset(target_display_->vsync_period_ns);
731
732 // TODO(jbates) Query vblank time from device, when such an API is
733 // available. This value (6.3%) was measured on A00 in low persistence mode.
734 int64_t vblank_ns = target_display_->vsync_period_ns * 63 / 1000;
735 offsets.right_ns = (target_display_->vsync_period_ns - vblank_ns) / 2;
736
737 // Check property for overriding right eye offset value.
738 offsets.right_ns =
739 property_get_int64(kRightEyeOffsetProperty, offsets.right_ns);
740
741 return offsets;
742 };
743
744 VsyncEyeOffsets vsync_eye_offsets = get_vsync_eye_offsets();
745
746 if (is_standalone_device_) {
747 // First, wait until boot finishes.
748 std::unique_lock<std::mutex> lock(post_thread_mutex_);
749 if (PostThreadCondWait(lock, -1, [this] { return boot_finished_; })) {
750 return;
751 }
752
753 // Then, wait until we're either leaving the quiescent state, or the boot
754 // finished display off timeout expires.
755 if (PostThreadCondWait(lock, kBootFinishedDisplayOffTimeoutSec,
756 [this] { return !post_thread_quiescent_; })) {
757 return;
758 }
759
760 LOG_ALWAYS_FATAL_IF(post_thread_state_ & PostThreadState::Suspended,
761 "Vr flinger should own the display by now.");
762 post_thread_resumed_ = true;
763 post_thread_ready_.notify_all();
764 if (!composer_)
765 CreateComposer();
766 }
767
768 while (1) {
769 ATRACE_NAME("HardwareComposer::PostThread");
770
771 // Check for updated config once per vsync.
772 UpdateConfigBuffer();
773
774 while (post_thread_quiescent_) {
775 std::unique_lock<std::mutex> lock(post_thread_mutex_);
776 ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
777
778 // Tear down resources.
779 OnPostThreadPaused();
780 was_running = false;
781 post_thread_resumed_ = false;
782 post_thread_ready_.notify_all();
783
784 if (PostThreadCondWait(lock, -1,
785 [this] { return !post_thread_quiescent_; })) {
786 // A true return value means we've been asked to quit.
787 return;
788 }
789
790 post_thread_resumed_ = true;
791 post_thread_ready_.notify_all();
792
793 ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
794 }
795
796 if (!composer_)
797 CreateComposer();
798
799 bool target_display_changed = UpdateTargetDisplay();
800 bool just_resumed_running = !was_running;
801 was_running = true;
802
803 if (target_display_changed)
804 vsync_eye_offsets = get_vsync_eye_offsets();
805
806 if (just_resumed_running) {
807 OnPostThreadResumed();
808
809 // Try to setup the scheduler policy if it failed during startup. Only
810 // attempt to do this on transitions from inactive to active to avoid
811 // spamming the system with RPCs and log messages.
812 if (!thread_policy_setup) {
813 thread_policy_setup =
814 SetThreadPolicy("graphics:high", "/system/performance");
815 }
816 }
817
818 if (target_display_changed || just_resumed_running) {
819 // Initialize the last vsync timestamp with the current time. The
820 // predictor below uses this time + the vsync interval in absolute time
821 // units for the initial delay. Once the driver starts reporting vsync the
822 // predictor will sync up with the real vsync.
823 last_vsync_timestamp_ = GetSystemClockNs();
824 vsync_prediction_interval_ = 1;
825 retire_fence_fds_.clear();
826 }
827
828 int64_t vsync_timestamp = 0;
829 {
830 TRACE_FORMAT("wait_vsync|vsync=%u;last_timestamp=%" PRId64
831 ";prediction_interval=%d|",
832 vsync_count_ + 1, last_vsync_timestamp_,
833 vsync_prediction_interval_);
834
835 auto status = WaitForPredictedVSync();
836 ALOGE_IF(
837 !status,
838 "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
839 status.GetErrorMessage().c_str());
840
841 // If there was an error either sleeping was interrupted due to pausing or
842 // there was an error getting the latest timestamp.
843 if (!status)
844 continue;
845
846 // Predicted vsync timestamp for this interval. This is stable because we
847 // use absolute time for the wakeup timer.
848 vsync_timestamp = status.get();
849 }
850
851 // Advance the vsync counter only if the system is keeping up with hardware
852 // vsync to give clients an indication of the delays.
853 if (vsync_prediction_interval_ == 1)
854 ++vsync_count_;
855
856 UpdateLayerConfig();
857
858 // Publish the vsync event.
859 if (vsync_ring_) {
860 DvrVsync vsync;
861 vsync.vsync_count = vsync_count_;
862 vsync.vsync_timestamp_ns = vsync_timestamp;
863 vsync.vsync_left_eye_offset_ns = vsync_eye_offsets.left_ns;
864 vsync.vsync_right_eye_offset_ns = vsync_eye_offsets.right_ns;
865 vsync.vsync_period_ns = target_display_->vsync_period_ns;
866
867 vsync_ring_->Publish(vsync);
868 }
869
870 // Signal all of the vsync clients. Because absolute time is used for the
871 // wakeup time below, this can take a little time if necessary.
872 if (vsync_callback_)
873 vsync_callback_(vsync_timestamp, /*frame_time_estimate*/ 0, vsync_count_);
874
875 {
876 // Sleep until shortly before vsync.
877 ATRACE_NAME("sleep");
878
879 const int64_t display_time_est_ns =
880 vsync_timestamp + target_display_->vsync_period_ns;
881 const int64_t now_ns = GetSystemClockNs();
882 const int64_t sleep_time_ns = display_time_est_ns - now_ns -
883 post_thread_config_.frame_post_offset_ns;
884 const int64_t wakeup_time_ns =
885 display_time_est_ns - post_thread_config_.frame_post_offset_ns;
886
887 ATRACE_INT64("sleep_time_ns", sleep_time_ns);
888 if (sleep_time_ns > 0) {
889 int error = SleepUntil(wakeup_time_ns);
890 ALOGE_IF(error < 0 && error != kPostThreadInterrupted,
891 "HardwareComposer::PostThread: Failed to sleep: %s",
892 strerror(-error));
893 // If the sleep was interrupted (error == kPostThreadInterrupted),
894 // we still go through and present this frame because we may have set
895 // layers earlier and we want to flush the Composer's internal command
896 // buffer by continuing through to validate and present.
897 }
898 }
899
900 {
901 auto status = composer_callback_->GetVsyncTime(target_display_->id);
902
903 // If we failed to read vsync there might be a problem with the driver.
904 // Since there's nothing we can do just behave as though we didn't get an
905 // updated vsync time and let the prediction continue.
906 const int64_t current_vsync_timestamp =
907 status ? status.get() : last_vsync_timestamp_;
908
909 const bool vsync_delayed =
910 last_vsync_timestamp_ == current_vsync_timestamp;
911 ATRACE_INT("vsync_delayed", vsync_delayed);
912
913 // If vsync was delayed advance the prediction interval and allow the
914 // fence logic in PostLayers() to skip the frame.
915 if (vsync_delayed) {
916 ALOGW(
917 "HardwareComposer::PostThread: VSYNC timestamp did not advance "
918 "since last frame: timestamp=%" PRId64 " prediction_interval=%d",
919 current_vsync_timestamp, vsync_prediction_interval_);
920 vsync_prediction_interval_++;
921 } else {
922 // We have an updated vsync timestamp, reset the prediction interval.
923 last_vsync_timestamp_ = current_vsync_timestamp;
924 vsync_prediction_interval_ = 1;
925 }
926 }
927
928 PostLayers(target_display_->id);
929 }
930 }
931
UpdateTargetDisplay()932 bool HardwareComposer::UpdateTargetDisplay() {
933 bool target_display_changed = false;
934 auto displays = composer_callback_->GetDisplays();
935 if (displays.external_display_was_hotplugged) {
936 bool was_using_external_display = !target_display_->is_primary;
937 if (was_using_external_display) {
938 // The external display was hotplugged, so make sure to ignore any bad
939 // display errors as we destroy the layers.
940 for (auto& layer: layers_)
941 layer.IgnoreBadDisplayErrorsOnDestroy(true);
942 }
943
944 if (displays.external_display) {
945 // External display was connected
946 external_display_ = GetDisplayParams(composer_.get(),
947 *displays.external_display, /*is_primary*/ false);
948
949 if (property_get_bool(kUseExternalDisplayProperty, false)) {
950 ALOGI("External display connected. Switching to external display.");
951 target_display_ = &(*external_display_);
952 target_display_changed = true;
953 } else {
954 ALOGI("External display connected, but sysprop %s is unset, so"
955 " using primary display.", kUseExternalDisplayProperty);
956 if (was_using_external_display) {
957 target_display_ = &primary_display_;
958 target_display_changed = true;
959 }
960 }
961 } else {
962 // External display was disconnected
963 external_display_ = std::nullopt;
964 if (was_using_external_display) {
965 ALOGI("External display disconnected. Switching to primary display.");
966 target_display_ = &primary_display_;
967 target_display_changed = true;
968 }
969 }
970 }
971
972 if (target_display_changed) {
973 // If we're switching to the external display, turn the primary display off.
974 if (!target_display_->is_primary) {
975 EnableDisplay(primary_display_, false);
976 }
977 // If we're switching to the primary display, and the external display is
978 // still connected, turn the external display off.
979 else if (target_display_->is_primary && external_display_) {
980 EnableDisplay(*external_display_, false);
981 }
982
983 // Turn the new target display on.
984 EnableDisplay(*target_display_, true);
985
986 // When we switch displays we need to recreate all the layers, so clear the
987 // current list, which will trigger layer recreation.
988 layers_.clear();
989 }
990
991 return target_display_changed;
992 }
993
994 // Checks for changes in the surface stack and updates the layer config to
995 // accomodate the new stack.
UpdateLayerConfig()996 void HardwareComposer::UpdateLayerConfig() {
997 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
998 {
999 std::unique_lock<std::mutex> lock(post_thread_mutex_);
1000
1001 if (!surfaces_changed_ && (!layers_.empty() || surfaces_.empty()))
1002 return;
1003
1004 surfaces = surfaces_;
1005 surfaces_changed_ = false;
1006 }
1007
1008 ATRACE_NAME("UpdateLayerConfig_HwLayers");
1009
1010 // Sort the new direct surface list by z-order to determine the relative order
1011 // of the surfaces. This relative order is used for the HWC z-order value to
1012 // insulate VrFlinger and HWC z-order semantics from each other.
1013 std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) {
1014 return a->z_order() < b->z_order();
1015 });
1016
1017 // Prepare a new layer stack, pulling in layers from the previous
1018 // layer stack that are still active and updating their attributes.
1019 std::vector<Layer> layers;
1020 size_t layer_index = 0;
1021 for (const auto& surface : surfaces) {
1022 // The bottom layer is opaque, other layers blend.
1023 HWC::BlendMode blending =
1024 layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
1025
1026 // Try to find a layer for this surface in the set of active layers.
1027 auto search =
1028 std::lower_bound(layers_.begin(), layers_.end(), surface->surface_id());
1029 const bool found = search != layers_.end() &&
1030 search->GetSurfaceId() == surface->surface_id();
1031 if (found) {
1032 // Update the attributes of the layer that may have changed.
1033 search->SetBlending(blending);
1034 search->SetZOrder(layer_index); // Relative z-order.
1035
1036 // Move the existing layer to the new layer set and remove the empty layer
1037 // object from the current set.
1038 layers.push_back(std::move(*search));
1039 layers_.erase(search);
1040 } else {
1041 // Insert a layer for the new surface.
1042 layers.emplace_back(composer_.get(), *target_display_, surface, blending,
1043 HWC::Composition::Device, layer_index);
1044 }
1045
1046 ALOGI_IF(
1047 TRACE,
1048 "HardwareComposer::UpdateLayerConfig: layer_index=%zu surface_id=%d",
1049 layer_index, layers[layer_index].GetSurfaceId());
1050
1051 layer_index++;
1052 }
1053
1054 // Sort the new layer stack by ascending surface id.
1055 std::sort(layers.begin(), layers.end());
1056
1057 // Replace the previous layer set with the new layer set. The destructor of
1058 // the previous set will clean up the remaining Layers that are not moved to
1059 // the new layer set.
1060 layers_ = std::move(layers);
1061
1062 ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
1063 layers_.size());
1064 }
1065
SetVSyncCallback(VSyncCallback callback)1066 void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
1067 vsync_callback_ = callback;
1068 }
1069
onHotplug(Hwc2::Display display,IComposerCallback::Connection conn)1070 Return<void> HardwareComposer::ComposerCallback::onHotplug(
1071 Hwc2::Display display, IComposerCallback::Connection conn) {
1072 std::lock_guard<std::mutex> lock(mutex_);
1073 ALOGI("onHotplug display=%" PRIu64 " conn=%d", display, conn);
1074
1075 bool is_primary = !got_first_hotplug_ || display == primary_display_.id;
1076
1077 // Our first onHotplug callback is always for the primary display.
1078 if (!got_first_hotplug_) {
1079 LOG_ALWAYS_FATAL_IF(conn != IComposerCallback::Connection::CONNECTED,
1080 "Initial onHotplug callback should be primary display connected");
1081 got_first_hotplug_ = true;
1082 } else if (is_primary) {
1083 ALOGE("Ignoring unexpected onHotplug() call for primary display");
1084 return Void();
1085 }
1086
1087 if (conn == IComposerCallback::Connection::CONNECTED) {
1088 if (!is_primary)
1089 external_display_ = DisplayInfo();
1090 DisplayInfo& display_info = is_primary ?
1091 primary_display_ : *external_display_;
1092 display_info.id = display;
1093
1094 std::array<char, 1024> buffer;
1095 snprintf(buffer.data(), buffer.size(),
1096 "/sys/class/graphics/fb%" PRIu64 "/vsync_event", display);
1097 if (LocalHandle handle{buffer.data(), O_RDONLY}) {
1098 ALOGI(
1099 "HardwareComposer::ComposerCallback::onHotplug: Driver supports "
1100 "vsync_event node for display %" PRIu64,
1101 display);
1102 display_info.driver_vsync_event_fd = std::move(handle);
1103 } else {
1104 ALOGI(
1105 "HardwareComposer::ComposerCallback::onHotplug: Driver does not "
1106 "support vsync_event node for display %" PRIu64,
1107 display);
1108 }
1109 } else if (conn == IComposerCallback::Connection::DISCONNECTED) {
1110 external_display_ = std::nullopt;
1111 }
1112
1113 if (!is_primary)
1114 external_display_was_hotplugged_ = true;
1115
1116 return Void();
1117 }
1118
onRefresh(Hwc2::Display)1119 Return<void> HardwareComposer::ComposerCallback::onRefresh(
1120 Hwc2::Display /*display*/) {
1121 return hardware::Void();
1122 }
1123
onVsync(Hwc2::Display display,int64_t timestamp)1124 Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display,
1125 int64_t timestamp) {
1126 DisplayInfo* display_info = GetDisplayInfo(display);
1127 if (display_info) {
1128 TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|",
1129 display, timestamp);
1130 display_info->callback_vsync_timestamp = timestamp;
1131 }
1132
1133 return Void();
1134 }
1135
1136 HardwareComposer::ComposerCallback::Displays
GetDisplays()1137 HardwareComposer::ComposerCallback::GetDisplays() {
1138 std::lock_guard<std::mutex> lock(mutex_);
1139 Displays displays;
1140 displays.primary_display = primary_display_.id;
1141 if (external_display_)
1142 displays.external_display = external_display_->id;
1143 if (external_display_was_hotplugged_) {
1144 external_display_was_hotplugged_ = false;
1145 displays.external_display_was_hotplugged = true;
1146 }
1147 return displays;
1148 }
1149
GetVsyncTime(hwc2_display_t display)1150 Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime(
1151 hwc2_display_t display) {
1152 DisplayInfo* display_info = GetDisplayInfo(display);
1153 if (!display_info) {
1154 ALOGW("Attempt to get vsync time for unknown display %" PRIu64, display);
1155 return ErrorStatus(EINVAL);
1156 }
1157
1158 // See if the driver supports direct vsync events.
1159 LocalHandle& event_fd = display_info->driver_vsync_event_fd;
1160 if (!event_fd) {
1161 // Fall back to returning the last timestamp returned by the vsync
1162 // callback.
1163 std::lock_guard<std::mutex> autolock(mutex_);
1164 return display_info->callback_vsync_timestamp;
1165 }
1166
1167 // When the driver supports the vsync_event sysfs node we can use it to
1168 // determine the latest vsync timestamp, even if the HWC callback has been
1169 // delayed.
1170
1171 // The driver returns data in the form "VSYNC=<timestamp ns>".
1172 std::array<char, 32> data;
1173 data.fill('\0');
1174
1175 // Seek back to the beginning of the event file.
1176 int ret = lseek(event_fd.Get(), 0, SEEK_SET);
1177 if (ret < 0) {
1178 const int error = errno;
1179 ALOGE(
1180 "HardwareComposer::ComposerCallback::GetVsyncTime: Failed to seek "
1181 "vsync event fd: %s",
1182 strerror(error));
1183 return ErrorStatus(error);
1184 }
1185
1186 // Read the vsync event timestamp.
1187 ret = read(event_fd.Get(), data.data(), data.size());
1188 if (ret < 0) {
1189 const int error = errno;
1190 ALOGE_IF(error != EAGAIN,
1191 "HardwareComposer::ComposerCallback::GetVsyncTime: Error "
1192 "while reading timestamp: %s",
1193 strerror(error));
1194 return ErrorStatus(error);
1195 }
1196
1197 int64_t timestamp;
1198 ret = sscanf(data.data(), "VSYNC=%" PRIu64,
1199 reinterpret_cast<uint64_t*>(×tamp));
1200 if (ret < 0) {
1201 const int error = errno;
1202 ALOGE(
1203 "HardwareComposer::ComposerCallback::GetVsyncTime: Error while "
1204 "parsing timestamp: %s",
1205 strerror(error));
1206 return ErrorStatus(error);
1207 }
1208
1209 return {timestamp};
1210 }
1211
1212 HardwareComposer::ComposerCallback::DisplayInfo*
GetDisplayInfo(hwc2_display_t display)1213 HardwareComposer::ComposerCallback::GetDisplayInfo(hwc2_display_t display) {
1214 if (display == primary_display_.id) {
1215 return &primary_display_;
1216 } else if (external_display_ && display == external_display_->id) {
1217 return &(*external_display_);
1218 }
1219 return nullptr;
1220 }
1221
Reset()1222 void Layer::Reset() {
1223 if (hardware_composer_layer_) {
1224 HWC::Error error =
1225 composer_->destroyLayer(display_params_.id, hardware_composer_layer_);
1226 if (error != HWC::Error::None &&
1227 (!ignore_bad_display_errors_on_destroy_ ||
1228 error != HWC::Error::BadDisplay)) {
1229 ALOGE("destroyLayer() failed for display %" PRIu64 ", layer %" PRIu64
1230 ". error: %s", display_params_.id, hardware_composer_layer_,
1231 error.to_string().c_str());
1232 }
1233 hardware_composer_layer_ = 0;
1234 }
1235
1236 z_order_ = 0;
1237 blending_ = HWC::BlendMode::None;
1238 composition_type_ = HWC::Composition::Invalid;
1239 target_composition_type_ = composition_type_;
1240 source_ = EmptyVariant{};
1241 acquire_fence_.Close();
1242 surface_rect_functions_applied_ = false;
1243 pending_visibility_settings_ = true;
1244 cached_buffer_map_.clear();
1245 ignore_bad_display_errors_on_destroy_ = false;
1246 }
1247
Layer(Hwc2::Composer * composer,const DisplayParams & display_params,const std::shared_ptr<DirectDisplaySurface> & surface,HWC::BlendMode blending,HWC::Composition composition_type,size_t z_order)1248 Layer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params,
1249 const std::shared_ptr<DirectDisplaySurface>& surface,
1250 HWC::BlendMode blending, HWC::Composition composition_type,
1251 size_t z_order)
1252 : composer_(composer),
1253 display_params_(display_params),
1254 z_order_{z_order},
1255 blending_{blending},
1256 target_composition_type_{composition_type},
1257 source_{SourceSurface{surface}} {
1258 CommonLayerSetup();
1259 }
1260
Layer(Hwc2::Composer * composer,const DisplayParams & display_params,const std::shared_ptr<IonBuffer> & buffer,HWC::BlendMode blending,HWC::Composition composition_type,size_t z_order)1261 Layer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params,
1262 const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
1263 HWC::Composition composition_type, size_t z_order)
1264 : composer_(composer),
1265 display_params_(display_params),
1266 z_order_{z_order},
1267 blending_{blending},
1268 target_composition_type_{composition_type},
1269 source_{SourceBuffer{buffer}} {
1270 CommonLayerSetup();
1271 }
1272
~Layer()1273 Layer::~Layer() { Reset(); }
1274
Layer(Layer && other)1275 Layer::Layer(Layer&& other) { *this = std::move(other); }
1276
operator =(Layer && other)1277 Layer& Layer::operator=(Layer&& other) {
1278 if (this != &other) {
1279 Reset();
1280 using std::swap;
1281 swap(composer_, other.composer_);
1282 swap(display_params_, other.display_params_);
1283 swap(hardware_composer_layer_, other.hardware_composer_layer_);
1284 swap(z_order_, other.z_order_);
1285 swap(blending_, other.blending_);
1286 swap(composition_type_, other.composition_type_);
1287 swap(target_composition_type_, other.target_composition_type_);
1288 swap(source_, other.source_);
1289 swap(acquire_fence_, other.acquire_fence_);
1290 swap(surface_rect_functions_applied_,
1291 other.surface_rect_functions_applied_);
1292 swap(pending_visibility_settings_, other.pending_visibility_settings_);
1293 swap(cached_buffer_map_, other.cached_buffer_map_);
1294 swap(ignore_bad_display_errors_on_destroy_,
1295 other.ignore_bad_display_errors_on_destroy_);
1296 }
1297 return *this;
1298 }
1299
UpdateBuffer(const std::shared_ptr<IonBuffer> & buffer)1300 void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
1301 if (source_.is<SourceBuffer>())
1302 std::get<SourceBuffer>(source_) = {buffer};
1303 }
1304
SetBlending(HWC::BlendMode blending)1305 void Layer::SetBlending(HWC::BlendMode blending) {
1306 if (blending_ != blending) {
1307 blending_ = blending;
1308 pending_visibility_settings_ = true;
1309 }
1310 }
1311
SetZOrder(size_t z_order)1312 void Layer::SetZOrder(size_t z_order) {
1313 if (z_order_ != z_order) {
1314 z_order_ = z_order;
1315 pending_visibility_settings_ = true;
1316 }
1317 }
1318
GetBuffer()1319 IonBuffer* Layer::GetBuffer() {
1320 struct Visitor {
1321 IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
1322 IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
1323 IonBuffer* operator()(EmptyVariant) { return nullptr; }
1324 };
1325 return source_.Visit(Visitor{});
1326 }
1327
UpdateVisibilitySettings()1328 void Layer::UpdateVisibilitySettings() {
1329 if (pending_visibility_settings_) {
1330 pending_visibility_settings_ = false;
1331
1332 HWC::Error error;
1333
1334 error = composer_->setLayerBlendMode(
1335 display_params_.id, hardware_composer_layer_,
1336 blending_.cast<Hwc2::IComposerClient::BlendMode>());
1337 ALOGE_IF(error != HWC::Error::None,
1338 "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
1339 error.to_string().c_str());
1340
1341 error = composer_->setLayerZOrder(display_params_.id,
1342 hardware_composer_layer_, z_order_);
1343 ALOGE_IF(error != HWC::Error::None,
1344 "Layer::UpdateLayerSettings: Error setting z_ order: %s",
1345 error.to_string().c_str());
1346 }
1347 }
1348
UpdateLayerSettings()1349 void Layer::UpdateLayerSettings() {
1350 HWC::Error error;
1351
1352 UpdateVisibilitySettings();
1353
1354 // TODO(eieio): Use surface attributes or some other mechanism to control
1355 // the layer display frame.
1356 error = composer_->setLayerDisplayFrame(
1357 display_params_.id, hardware_composer_layer_,
1358 {0, 0, display_params_.width, display_params_.height});
1359 ALOGE_IF(error != HWC::Error::None,
1360 "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
1361 error.to_string().c_str());
1362
1363 error = composer_->setLayerVisibleRegion(
1364 display_params_.id, hardware_composer_layer_,
1365 {{0, 0, display_params_.width, display_params_.height}});
1366 ALOGE_IF(error != HWC::Error::None,
1367 "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
1368 error.to_string().c_str());
1369
1370 error = composer_->setLayerPlaneAlpha(display_params_.id,
1371 hardware_composer_layer_, 1.0f);
1372 ALOGE_IF(error != HWC::Error::None,
1373 "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
1374 error.to_string().c_str());
1375 }
1376
CommonLayerSetup()1377 void Layer::CommonLayerSetup() {
1378 HWC::Error error = composer_->createLayer(display_params_.id,
1379 &hardware_composer_layer_);
1380 ALOGE_IF(error != HWC::Error::None,
1381 "Layer::CommonLayerSetup: Failed to create layer on primary "
1382 "display: %s",
1383 error.to_string().c_str());
1384 UpdateLayerSettings();
1385 }
1386
CheckAndUpdateCachedBuffer(std::size_t slot,int buffer_id)1387 bool Layer::CheckAndUpdateCachedBuffer(std::size_t slot, int buffer_id) {
1388 auto search = cached_buffer_map_.find(slot);
1389 if (search != cached_buffer_map_.end() && search->second == buffer_id)
1390 return true;
1391
1392 // Assign or update the buffer slot.
1393 if (buffer_id >= 0)
1394 cached_buffer_map_[slot] = buffer_id;
1395 return false;
1396 }
1397
Prepare()1398 void Layer::Prepare() {
1399 int right, bottom, id;
1400 sp<GraphicBuffer> handle;
1401 std::size_t slot;
1402
1403 // Acquire the next buffer according to the type of source.
1404 IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
1405 std::tie(right, bottom, id, handle, acquire_fence_, slot) =
1406 source.Acquire();
1407 });
1408
1409 TRACE_FORMAT("Layer::Prepare|buffer_id=%d;slot=%zu|", id, slot);
1410
1411 // Update any visibility (blending, z-order) changes that occurred since
1412 // last prepare.
1413 UpdateVisibilitySettings();
1414
1415 // When a layer is first setup there may be some time before the first
1416 // buffer arrives. Setup the HWC layer as a solid color to stall for time
1417 // until the first buffer arrives. Once the first buffer arrives there will
1418 // always be a buffer for the frame even if it is old.
1419 if (!handle.get()) {
1420 if (composition_type_ == HWC::Composition::Invalid) {
1421 composition_type_ = HWC::Composition::SolidColor;
1422 composer_->setLayerCompositionType(
1423 display_params_.id, hardware_composer_layer_,
1424 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1425 Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
1426 composer_->setLayerColor(display_params_.id, hardware_composer_layer_,
1427 layer_color);
1428 } else {
1429 // The composition type is already set. Nothing else to do until a
1430 // buffer arrives.
1431 }
1432 } else {
1433 if (composition_type_ != target_composition_type_) {
1434 composition_type_ = target_composition_type_;
1435 composer_->setLayerCompositionType(
1436 display_params_.id, hardware_composer_layer_,
1437 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1438 }
1439
1440 // See if the HWC cache already has this buffer.
1441 const bool cached = CheckAndUpdateCachedBuffer(slot, id);
1442 if (cached)
1443 handle = nullptr;
1444
1445 HWC::Error error{HWC::Error::None};
1446 error =
1447 composer_->setLayerBuffer(display_params_.id, hardware_composer_layer_,
1448 slot, handle, acquire_fence_.Get());
1449
1450 ALOGE_IF(error != HWC::Error::None,
1451 "Layer::Prepare: Error setting layer buffer: %s",
1452 error.to_string().c_str());
1453
1454 if (!surface_rect_functions_applied_) {
1455 const float float_right = right;
1456 const float float_bottom = bottom;
1457 error = composer_->setLayerSourceCrop(display_params_.id,
1458 hardware_composer_layer_,
1459 {0, 0, float_right, float_bottom});
1460
1461 ALOGE_IF(error != HWC::Error::None,
1462 "Layer::Prepare: Error setting layer source crop: %s",
1463 error.to_string().c_str());
1464
1465 surface_rect_functions_applied_ = true;
1466 }
1467 }
1468 }
1469
Finish(int release_fence_fd)1470 void Layer::Finish(int release_fence_fd) {
1471 IfAnyOf<SourceSurface, SourceBuffer>::Call(
1472 &source_, [release_fence_fd](auto& source) {
1473 source.Finish(LocalHandle(release_fence_fd));
1474 });
1475 }
1476
Drop()1477 void Layer::Drop() { acquire_fence_.Close(); }
1478
1479 } // namespace dvr
1480 } // namespace android
1481