blob: 4c0828475243d5c54f54ade281921fe801f8843e [file] [log] [blame]
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001#include "hardware_composer.h"
2
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08003#include <cutils/properties.h>
4#include <cutils/sched_policy.h>
5#include <fcntl.h>
Corey Tabaka2251d822017-04-20 16:04:07 -07006#include <log/log.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08007#include <poll.h>
8#include <sync/sync.h>
9#include <sys/eventfd.h>
10#include <sys/prctl.h>
11#include <sys/resource.h>
12#include <sys/system_properties.h>
13#include <sys/timerfd.h>
Corey Tabaka2251d822017-04-20 16:04:07 -070014#include <time.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080015#include <unistd.h>
16#include <utils/Trace.h>
17
18#include <algorithm>
Corey Tabaka2251d822017-04-20 16:04:07 -070019#include <chrono>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080020#include <functional>
21#include <map>
22
Corey Tabaka2251d822017-04-20 16:04:07 -070023#include <dvr/dvr_display_types.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080024#include <dvr/performance_client_api.h>
25#include <private/dvr/clock_ns.h>
Corey Tabaka2251d822017-04-20 16:04:07 -070026#include <private/dvr/ion_buffer.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080027#include <private/dvr/pose_client_internal.h>
28#include <private/dvr/sync_util.h>
29
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080030using android::pdx::LocalHandle;
Corey Tabaka2251d822017-04-20 16:04:07 -070031using android::pdx::rpc::EmptyVariant;
32using android::pdx::rpc::IfAnyOf;
33
34using namespace std::chrono_literals;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080035
36namespace android {
37namespace dvr {
38
39namespace {
40
41// If the number of pending fences goes over this count at the point when we
42// are about to submit a new frame to HWC, we will drop the frame. This should
43// be a signal that the display driver has begun queuing frames. Note that with
44// smart displays (with RAM), the fence is signaled earlier than the next vsync,
45// at the point when the DMA to the display completes. Currently we use a smart
46// display and the EDS timing coincides with zero pending fences, so this is 0.
47constexpr int kAllowedPendingFenceCount = 0;
48
Corey Tabaka2251d822017-04-20 16:04:07 -070049// Offset before vsync to submit frames to hardware composer.
50constexpr int64_t kFramePostOffsetNs = 4000000; // 4ms
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080051
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080052const char kBacklightBrightnessSysFile[] =
53 "/sys/class/leds/lcd-backlight/brightness";
54
55const char kPrimaryDisplayVSyncEventFile[] =
56 "/sys/class/graphics/fb0/vsync_event";
57
58const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
59
60const char kDvrPerformanceProperty[] = "sys.dvr.performance";
61
Luke Song4b788322017-03-24 14:17:31 -070062const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080063
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080064// 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.
70inline int64_t GetPosePredictionTimeOffset(int64_t vsync_period_ns) {
71 return (vsync_period_ns * 150) / 100;
72}
73
Corey Tabaka2251d822017-04-20 16:04:07 -070074// Attempts to set the scheduler class and partiton for the current thread.
75// Returns true on success or false on failure.
76bool 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
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080097} // anonymous namespace
98
Corey Tabaka2251d822017-04-20 16:04:07 -070099// Layer static data.
100Hwc2::Composer* Layer::hwc2_hidl_;
101const HWCDisplayMetrics* Layer::display_metrics_;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800102
Corey Tabaka2251d822017-04-20 16:04:07 -0700103// HardwareComposer static data;
104constexpr size_t HardwareComposer::kMaxHardwareLayers;
105
106HardwareComposer::HardwareComposer()
107 : HardwareComposer(nullptr, RequestDisplayCallback()) {}
108
109HardwareComposer::HardwareComposer(
110 Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800111 : initialized_(false),
112 hwc2_hidl_(hwc2_hidl),
Corey Tabaka2251d822017-04-20 16:04:07 -0700113 request_display_callback_(request_display_callback),
114 callbacks_(new ComposerCallback) {}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800115
116HardwareComposer::~HardwareComposer(void) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700117 UpdatePostThreadState(PostThreadState::Quit, true);
118 if (post_thread_.joinable())
Steven Thomas050b2c82017-03-06 11:45:16 -0800119 post_thread_.join();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800120}
121
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800122bool HardwareComposer::Initialize() {
123 if (initialized_) {
124 ALOGE("HardwareComposer::Initialize: already initialized.");
125 return false;
126 }
127
Corey Tabaka2251d822017-04-20 16:04:07 -0700128 HWC::Error error = HWC::Error::None;
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800129
130 Hwc2::Config config;
Corey Tabaka2251d822017-04-20 16:04:07 -0700131 error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800132
Corey Tabaka2251d822017-04-20 16:04:07 -0700133 if (error != HWC::Error::None) {
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800134 ALOGE("HardwareComposer: Failed to get current display config : %d",
135 config);
136 return false;
137 }
138
Corey Tabaka2251d822017-04-20 16:04:07 -0700139 error =
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800140 GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
141
Corey Tabaka2251d822017-04-20 16:04:07 -0700142 if (error != HWC::Error::None) {
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800143 ALOGE(
144 "HardwareComposer: Failed to get display attributes for current "
145 "configuration : %d",
Corey Tabaka2251d822017-04-20 16:04:07 -0700146 error.value);
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800147 return false;
148 }
149
150 ALOGI(
151 "HardwareComposer: primary display attributes: width=%d height=%d "
152 "vsync_period_ns=%d DPI=%dx%d",
153 native_display_metrics_.width, native_display_metrics_.height,
154 native_display_metrics_.vsync_period_ns, native_display_metrics_.dpi.x,
155 native_display_metrics_.dpi.y);
156
157 // Set the display metrics but never use rotation to avoid the long latency of
158 // rotation processing in hwc.
159 display_transform_ = HWC_TRANSFORM_NONE;
160 display_metrics_ = native_display_metrics_;
161
Corey Tabaka2251d822017-04-20 16:04:07 -0700162 // Pass hwc instance and metrics to setup globals for Layer.
163 Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
164
165 post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
Steven Thomas050b2c82017-03-06 11:45:16 -0800166 LOG_ALWAYS_FATAL_IF(
Corey Tabaka2251d822017-04-20 16:04:07 -0700167 !post_thread_event_fd_,
Steven Thomas050b2c82017-03-06 11:45:16 -0800168 "HardwareComposer: Failed to create interrupt event fd : %s",
169 strerror(errno));
170
171 post_thread_ = std::thread(&HardwareComposer::PostThread, this);
172
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800173 initialized_ = true;
174
175 return initialized_;
176}
177
Steven Thomas050b2c82017-03-06 11:45:16 -0800178void HardwareComposer::Enable() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700179 UpdatePostThreadState(PostThreadState::Suspended, false);
Steven Thomas050b2c82017-03-06 11:45:16 -0800180}
181
182void HardwareComposer::Disable() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700183 UpdatePostThreadState(PostThreadState::Suspended, true);
Steven Thomas050b2c82017-03-06 11:45:16 -0800184}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800185
Corey Tabaka2251d822017-04-20 16:04:07 -0700186// Update the post thread quiescent state based on idle and suspended inputs.
187void 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 // Wait until the post thread is in the requested state.
217 post_thread_ready_.wait(lock, [this, effective_suspend] {
218 return effective_suspend != post_thread_resumed_;
219 });
Steven Thomas050b2c82017-03-06 11:45:16 -0800220}
Steven Thomas282a5ed2017-02-07 18:07:01 -0800221
Steven Thomas050b2c82017-03-06 11:45:16 -0800222void HardwareComposer::OnPostThreadResumed() {
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700223 hwc2_hidl_->resetCommands();
224
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800225 // Connect to pose service.
226 pose_client_ = dvrPoseCreate();
227 ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
228
Corey Tabaka2251d822017-04-20 16:04:07 -0700229 // HIDL HWC seems to have an internal race condition. If we submit a frame too
230 // soon after turning on VSync we don't get any VSync signals. Give poor HWC
231 // implementations a chance to enable VSync before we continue.
232 EnableVsync(false);
233 std::this_thread::sleep_for(100ms);
Steven Thomas050b2c82017-03-06 11:45:16 -0800234 EnableVsync(true);
Corey Tabaka2251d822017-04-20 16:04:07 -0700235 std::this_thread::sleep_for(100ms);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800236
Steven Thomas050b2c82017-03-06 11:45:16 -0800237 // TODO(skiazyk): We need to do something about accessing this directly,
238 // supposedly there is a backlight service on the way.
239 // TODO(steventhomas): When we change the backlight setting, will surface
240 // flinger (or something else) set it back to its original value once we give
241 // control of the display back to surface flinger?
242 SetBacklightBrightness(255);
Steven Thomas282a5ed2017-02-07 18:07:01 -0800243
Steven Thomas050b2c82017-03-06 11:45:16 -0800244 // Trigger target-specific performance mode change.
245 property_set(kDvrPerformanceProperty, "performance");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800246}
247
Steven Thomas050b2c82017-03-06 11:45:16 -0800248void HardwareComposer::OnPostThreadPaused() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700249 retire_fence_fds_.clear();
Steven Thomas050b2c82017-03-06 11:45:16 -0800250 display_surfaces_.clear();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800251
Corey Tabaka2251d822017-04-20 16:04:07 -0700252 for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
253 layers_[i].Reset();
254 }
255 active_layer_count_ = 0;
Steven Thomas050b2c82017-03-06 11:45:16 -0800256
257 if (pose_client_) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800258 dvrPoseDestroy(pose_client_);
Steven Thomas050b2c82017-03-06 11:45:16 -0800259 pose_client_ = nullptr;
260 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800261
Steven Thomas050b2c82017-03-06 11:45:16 -0800262 EnableVsync(false);
263
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700264 hwc2_hidl_->resetCommands();
265
Steven Thomas050b2c82017-03-06 11:45:16 -0800266 // Trigger target-specific performance mode change.
267 property_set(kDvrPerformanceProperty, "idle");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800268}
269
Corey Tabaka2251d822017-04-20 16:04:07 -0700270HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800271 uint32_t num_types;
272 uint32_t num_requests;
Corey Tabaka2251d822017-04-20 16:04:07 -0700273 HWC::Error error =
274 hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800275
276 if (error == HWC2_ERROR_HAS_CHANGES) {
277 // TODO(skiazyk): We might need to inspect the requested changes first, but
278 // so far it seems like we shouldn't ever hit a bad state.
279 // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
280 // display);
Corey Tabaka2251d822017-04-20 16:04:07 -0700281 error = hwc2_hidl_->acceptDisplayChanges(display);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800282 }
283
284 return error;
285}
286
287int32_t HardwareComposer::EnableVsync(bool enabled) {
288 return (int32_t)hwc2_hidl_->setVsyncEnabled(
289 HWC_DISPLAY_PRIMARY,
290 (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
291 : HWC2_VSYNC_DISABLE));
292}
293
Corey Tabaka2251d822017-04-20 16:04:07 -0700294HWC::Error HardwareComposer::Present(hwc2_display_t display) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800295 int32_t present_fence;
Corey Tabaka2251d822017-04-20 16:04:07 -0700296 HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800297
298 // According to the documentation, this fence is signaled at the time of
299 // vsync/DMA for physical displays.
Corey Tabaka2251d822017-04-20 16:04:07 -0700300 if (error == HWC::Error::None) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800301 ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
302 retire_fence_fds_.emplace_back(present_fence);
303 } else {
304 ATRACE_INT("HardwareComposer: PresentResult", error);
305 }
306
307 return error;
308}
309
Corey Tabaka2251d822017-04-20 16:04:07 -0700310HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
311 hwc2_config_t config,
312 hwc2_attribute_t attribute,
313 int32_t* out_value) const {
314 return hwc2_hidl_->getDisplayAttribute(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800315 display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
316}
317
Corey Tabaka2251d822017-04-20 16:04:07 -0700318HWC::Error HardwareComposer::GetDisplayMetrics(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800319 hwc2_display_t display, hwc2_config_t config,
320 HWCDisplayMetrics* out_metrics) const {
Corey Tabaka2251d822017-04-20 16:04:07 -0700321 HWC::Error error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800322
Corey Tabaka2251d822017-04-20 16:04:07 -0700323 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
324 &out_metrics->width);
325 if (error != HWC::Error::None) {
326 ALOGE(
327 "HardwareComposer::GetDisplayMetrics: Failed to get display width: %s",
328 error.to_string().c_str());
329 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800330 }
331
Corey Tabaka2251d822017-04-20 16:04:07 -0700332 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
333 &out_metrics->height);
334 if (error != HWC::Error::None) {
335 ALOGE(
336 "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
337 error.to_string().c_str());
338 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800339 }
340
Corey Tabaka2251d822017-04-20 16:04:07 -0700341 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
342 &out_metrics->vsync_period_ns);
343 if (error != HWC::Error::None) {
344 ALOGE(
345 "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
346 error.to_string().c_str());
347 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800348 }
349
Corey Tabaka2251d822017-04-20 16:04:07 -0700350 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
351 &out_metrics->dpi.x);
352 if (error != HWC::Error::None) {
353 ALOGE(
354 "HardwareComposer::GetDisplayMetrics: Failed to get display DPI X: %s",
355 error.to_string().c_str());
356 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800357 }
358
Corey Tabaka2251d822017-04-20 16:04:07 -0700359 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
360 &out_metrics->dpi.y);
361 if (error != HWC::Error::None) {
362 ALOGE(
363 "HardwareComposer::GetDisplayMetrics: Failed to get display DPI Y: %s",
364 error.to_string().c_str());
365 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800366 }
367
Corey Tabaka2251d822017-04-20 16:04:07 -0700368 return HWC::Error::None;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800369}
370
Corey Tabaka2251d822017-04-20 16:04:07 -0700371std::string HardwareComposer::Dump() { return hwc2_hidl_->dumpDebugInfo(); }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800372
Corey Tabaka2251d822017-04-20 16:04:07 -0700373void HardwareComposer::PostLayers() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800374 ATRACE_NAME("HardwareComposer::PostLayers");
375
376 // Setup the hardware composer layers with current buffers.
377 for (size_t i = 0; i < active_layer_count_; i++) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700378 layers_[i].Prepare();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800379 }
380
Corey Tabaka2251d822017-04-20 16:04:07 -0700381 HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
382 if (error != HWC::Error::None) {
383 ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
384 error.to_string().c_str());
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700385 return;
386 }
387
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800388 // Now that we have taken in a frame from the application, we have a chance
389 // to drop the frame before passing the frame along to HWC.
390 // If the display driver has become backed up, we detect it here and then
391 // react by skipping this frame to catch up latency.
392 while (!retire_fence_fds_.empty() &&
393 (!retire_fence_fds_.front() ||
394 sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) {
395 // There are only 2 fences in here, no performance problem to shift the
396 // array of ints.
397 retire_fence_fds_.erase(retire_fence_fds_.begin());
398 }
399
400 const bool is_frame_pending = IsFramePendingInDriver();
401 const bool is_fence_pending =
402 retire_fence_fds_.size() > kAllowedPendingFenceCount;
403
404 if (is_fence_pending || is_frame_pending) {
405 ATRACE_INT("frame_skip_count", ++frame_skip_count_);
406
407 ALOGW_IF(is_frame_pending, "Warning: frame already queued, dropping frame");
408 ALOGW_IF(is_fence_pending,
409 "Warning: dropping a frame to catch up with HWC (pending = %zd)",
410 retire_fence_fds_.size());
411
412 for (size_t i = 0; i < active_layer_count_; i++) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700413 layers_[i].Drop();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800414 }
415 return;
416 } else {
417 // Make the transition more obvious in systrace when the frame skip happens
418 // above.
419 ATRACE_INT("frame_skip_count", 0);
420 }
421
422#if TRACE
423 for (size_t i = 0; i < active_layer_count_; i++)
Corey Tabaka2251d822017-04-20 16:04:07 -0700424 ALOGI("HardwareComposer::PostLayers: layer=%zu composition=%s", i,
425 layers_[i].GetCompositionType().to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800426#endif
427
Corey Tabaka2251d822017-04-20 16:04:07 -0700428 error = Present(HWC_DISPLAY_PRIMARY);
429 if (error != HWC::Error::None) {
430 ALOGE("HardwareComposer::PostLayers: Present failed: %s",
431 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800432 return;
433 }
434
435 std::vector<Hwc2::Layer> out_layers;
436 std::vector<int> out_fences;
Corey Tabaka2251d822017-04-20 16:04:07 -0700437 error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
438 &out_fences);
439 ALOGE_IF(error != HWC::Error::None,
440 "HardwareComposer::PostLayers: Failed to get release fences: %s",
441 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800442
443 // Perform post-frame bookkeeping. Unused layers are a no-op.
Corey Tabaka2251d822017-04-20 16:04:07 -0700444 uint32_t num_elements = out_layers.size();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800445 for (size_t i = 0; i < num_elements; ++i) {
446 for (size_t j = 0; j < active_layer_count_; ++j) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700447 if (layers_[j].GetLayerHandle() == out_layers[i]) {
448 layers_[j].Finish(out_fences[i]);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800449 }
450 }
451 }
452}
453
Steven Thomas050b2c82017-03-06 11:45:16 -0800454void HardwareComposer::SetDisplaySurfaces(
Corey Tabaka2251d822017-04-20 16:04:07 -0700455 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
Jin Qian7480c062017-03-21 00:04:15 +0000456 ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
457 surfaces.size());
Corey Tabaka2251d822017-04-20 16:04:07 -0700458 const bool display_idle = surfaces.size() == 0;
459 {
460 std::unique_lock<std::mutex> lock(post_thread_mutex_);
461 pending_surfaces_ = std::move(surfaces);
462 }
463
464 // Set idle state based on whether there are any surfaces to handle.
465 UpdatePostThreadState(PostThreadState::Idle, display_idle);
466
467 // XXX: TEMPORARY
468 // Request control of the display based on whether there are any surfaces to
469 // handle. This callback sets the post thread active state once the transition
470 // is complete in SurfaceFlinger.
471 // TODO(eieio): Unify the control signal used to move SurfaceFlinger into VR
472 // mode. Currently this is hooked up to persistent VR mode, but perhaps this
473 // makes more sense to control it from VrCore, which could in turn base its
474 // decision on persistent VR mode.
475 if (request_display_callback_)
476 request_display_callback_(!display_idle);
Steven Thomas050b2c82017-03-06 11:45:16 -0800477}
Jin Qian7480c062017-03-21 00:04:15 +0000478
Corey Tabaka2251d822017-04-20 16:04:07 -0700479int HardwareComposer::PostThreadPollInterruptible(
480 const pdx::LocalHandle& event_fd, int requested_events) {
Steven Thomas050b2c82017-03-06 11:45:16 -0800481 pollfd pfd[2] = {
482 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700483 .fd = event_fd.Get(),
Steven Thomas66747c12017-03-22 18:45:31 -0700484 .events = static_cast<short>(requested_events),
485 .revents = 0,
Steven Thomas050b2c82017-03-06 11:45:16 -0800486 },
487 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700488 .fd = post_thread_event_fd_.Get(),
Steven Thomas050b2c82017-03-06 11:45:16 -0800489 .events = POLLPRI | POLLIN,
490 .revents = 0,
491 },
492 };
493 int ret, error;
494 do {
495 ret = poll(pfd, 2, -1);
496 error = errno;
497 ALOGW_IF(ret < 0,
498 "HardwareComposer::PostThreadPollInterruptible: Error during "
499 "poll(): %s (%d)",
500 strerror(error), error);
501 } while (ret < 0 && error == EINTR);
502
503 if (ret < 0) {
504 return -error;
505 } else if (pfd[0].revents != 0) {
506 return 0;
507 } else if (pfd[1].revents != 0) {
508 ALOGI("VrHwcPost thread interrupted");
509 return kPostThreadInterrupted;
510 } else {
511 return 0;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800512 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800513}
514
515// Reads the value of the display driver wait_pingpong state. Returns 0 or 1
516// (the value of the state) on success or a negative error otherwise.
517// TODO(eieio): This is pretty driver specific, this should be moved to a
518// separate class eventually.
519int HardwareComposer::ReadWaitPPState() {
520 // Gracefully handle when the kernel does not support this feature.
521 if (!primary_display_wait_pp_fd_)
522 return 0;
523
524 const int wait_pp_fd = primary_display_wait_pp_fd_.Get();
525 int ret, error;
526
527 ret = lseek(wait_pp_fd, 0, SEEK_SET);
528 if (ret < 0) {
529 error = errno;
530 ALOGE("HardwareComposer::ReadWaitPPState: Failed to seek wait_pp fd: %s",
531 strerror(error));
532 return -error;
533 }
534
535 char data = -1;
536 ret = read(wait_pp_fd, &data, sizeof(data));
537 if (ret < 0) {
538 error = errno;
539 ALOGE("HardwareComposer::ReadWaitPPState: Failed to read wait_pp state: %s",
540 strerror(error));
541 return -error;
542 }
543
544 switch (data) {
545 case '0':
546 return 0;
547 case '1':
548 return 1;
549 default:
550 ALOGE(
551 "HardwareComposer::ReadWaitPPState: Unexpected value for wait_pp: %d",
552 data);
553 return -EINVAL;
554 }
555}
556
557// Reads the timestamp of the last vsync from the display driver.
558// TODO(eieio): This is pretty driver specific, this should be moved to a
559// separate class eventually.
560int HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) {
561 const int event_fd = primary_display_vsync_event_fd_.Get();
562 int ret, error;
563
564 // The driver returns data in the form "VSYNC=<timestamp ns>".
565 std::array<char, 32> data;
566 data.fill('\0');
567
568 // Seek back to the beginning of the event file.
569 ret = lseek(event_fd, 0, SEEK_SET);
570 if (ret < 0) {
571 error = errno;
572 ALOGE(
573 "HardwareComposer::ReadVSyncTimestamp: Failed to seek vsync event fd: "
574 "%s",
575 strerror(error));
576 return -error;
577 }
578
579 // Read the vsync event timestamp.
580 ret = read(event_fd, data.data(), data.size());
581 if (ret < 0) {
582 error = errno;
583 ALOGE_IF(
584 error != EAGAIN,
585 "HardwareComposer::ReadVSyncTimestamp: Error while reading timestamp: "
586 "%s",
587 strerror(error));
588 return -error;
589 }
590
591 ret = sscanf(data.data(), "VSYNC=%" PRIu64,
592 reinterpret_cast<uint64_t*>(timestamp));
593 if (ret < 0) {
594 error = errno;
595 ALOGE(
596 "HardwareComposer::ReadVSyncTimestamp: Error while parsing timestamp: "
597 "%s",
598 strerror(error));
599 return -error;
600 }
601
602 return 0;
603}
604
605// Blocks until the next vsync event is signaled by the display driver.
606// TODO(eieio): This is pretty driver specific, this should be moved to a
607// separate class eventually.
Steven Thomas050b2c82017-03-06 11:45:16 -0800608int HardwareComposer::BlockUntilVSync() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700609 // Vsync is signaled by POLLPRI on the fb vsync node.
610 return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800611}
612
613// Waits for the next vsync and returns the timestamp of the vsync event. If
614// vsync already passed since the last call, returns the latest vsync timestamp
615// instead of blocking. This method updates the last_vsync_timeout_ in the
616// process.
617//
618// TODO(eieio): This is pretty driver specific, this should be moved to a
619// separate class eventually.
620int HardwareComposer::WaitForVSync(int64_t* timestamp) {
621 int error;
622
623 // Get the current timestamp and decide what to do.
624 while (true) {
625 int64_t current_vsync_timestamp;
626 error = ReadVSyncTimestamp(&current_vsync_timestamp);
627 if (error < 0 && error != -EAGAIN)
628 return error;
629
630 if (error == -EAGAIN) {
631 // Vsync was turned off, wait for the next vsync event.
Steven Thomas050b2c82017-03-06 11:45:16 -0800632 error = BlockUntilVSync();
633 if (error < 0 || error == kPostThreadInterrupted)
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800634 return error;
635
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800636 // Try again to get the timestamp for this new vsync interval.
637 continue;
638 }
639
640 // Check that we advanced to a later vsync interval.
641 if (TimestampGT(current_vsync_timestamp, last_vsync_timestamp_)) {
642 *timestamp = last_vsync_timestamp_ = current_vsync_timestamp;
643 return 0;
644 }
645
646 // See how close we are to the next expected vsync. If we're within 1ms,
647 // sleep for 1ms and try again.
648 const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
Corey Tabaka2251d822017-04-20 16:04:07 -0700649 const int64_t threshold_ns = 1000000; // 1ms
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800650
651 const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
652 const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
653
654 if (distance_to_vsync_est > threshold_ns) {
655 // Wait for vsync event notification.
Steven Thomas050b2c82017-03-06 11:45:16 -0800656 error = BlockUntilVSync();
657 if (error < 0 || error == kPostThreadInterrupted)
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800658 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800659 } else {
Steven Thomas050b2c82017-03-06 11:45:16 -0800660 // Sleep for a short time (1 millisecond) before retrying.
Corey Tabaka2251d822017-04-20 16:04:07 -0700661 error = SleepUntil(GetSystemClockNs() + threshold_ns);
Steven Thomas050b2c82017-03-06 11:45:16 -0800662 if (error < 0 || error == kPostThreadInterrupted)
663 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800664 }
665 }
666}
667
668int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
669 const int timer_fd = vsync_sleep_timer_fd_.Get();
670 const itimerspec wakeup_itimerspec = {
671 .it_interval = {.tv_sec = 0, .tv_nsec = 0},
672 .it_value = NsToTimespec(wakeup_timestamp),
673 };
674 int ret =
675 timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr);
676 int error = errno;
677 if (ret < 0) {
678 ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s",
679 strerror(error));
680 return -error;
681 }
682
Corey Tabaka2251d822017-04-20 16:04:07 -0700683 return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800684}
685
686void HardwareComposer::PostThread() {
687 // NOLINTNEXTLINE(runtime/int)
Steven Thomas050b2c82017-03-06 11:45:16 -0800688 prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800689
Corey Tabaka2251d822017-04-20 16:04:07 -0700690 // Set the scheduler to SCHED_FIFO with high priority. If this fails here
691 // there may have been a startup timing issue between this thread and
692 // performanced. Try again later when this thread becomes active.
693 bool thread_policy_setup =
694 SetThreadPolicy("graphics:high", "/system/performance");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800695
Steven Thomas050b2c82017-03-06 11:45:16 -0800696#if ENABLE_BACKLIGHT_BRIGHTNESS
697 // TODO(hendrikw): This isn't required at the moment. It's possible that there
698 // is another method to access this when needed.
699 // Open the backlight brightness control sysfs node.
700 backlight_brightness_fd_ = LocalHandle(kBacklightBrightnessSysFile, O_RDWR);
701 ALOGW_IF(!backlight_brightness_fd_,
702 "HardwareComposer: Failed to open backlight brightness control: %s",
703 strerror(errno));
Corey Tabaka2251d822017-04-20 16:04:07 -0700704#endif // ENABLE_BACKLIGHT_BRIGHTNESS
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800705
Steven Thomas050b2c82017-03-06 11:45:16 -0800706 // Open the vsync event node for the primary display.
707 // TODO(eieio): Move this into a platform-specific class.
708 primary_display_vsync_event_fd_ =
709 LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY);
710 ALOGE_IF(!primary_display_vsync_event_fd_,
711 "HardwareComposer: Failed to open vsync event node for primary "
712 "display: %s",
713 strerror(errno));
714
715 // Open the wait pingpong status node for the primary display.
716 // TODO(eieio): Move this into a platform-specific class.
717 primary_display_wait_pp_fd_ =
718 LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY);
719 ALOGW_IF(
720 !primary_display_wait_pp_fd_,
721 "HardwareComposer: Failed to open wait_pp node for primary display: %s",
722 strerror(errno));
723
724 // Create a timerfd based on CLOCK_MONOTINIC.
725 vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
726 LOG_ALWAYS_FATAL_IF(
727 !vsync_sleep_timer_fd_,
728 "HardwareComposer: Failed to create vsync sleep timerfd: %s",
729 strerror(errno));
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800730
731 const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
732 const int64_t photon_offset_ns = GetPosePredictionTimeOffset(ns_per_frame);
733
734 // TODO(jbates) Query vblank time from device, when such an API is available.
735 // This value (6.3%) was measured on A00 in low persistence mode.
736 int64_t vblank_ns = ns_per_frame * 63 / 1000;
737 int64_t right_eye_photon_offset_ns = (ns_per_frame - vblank_ns) / 2;
738
739 // Check property for overriding right eye offset value.
740 right_eye_photon_offset_ns =
741 property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
742
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800743 // Storage for retrieving fence info.
744 FenceInfoBuffer fence_info_buffer;
745
Steven Thomas050b2c82017-03-06 11:45:16 -0800746 bool was_running = false;
747
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800748 while (1) {
749 ATRACE_NAME("HardwareComposer::PostThread");
750
Corey Tabaka2251d822017-04-20 16:04:07 -0700751 while (post_thread_quiescent_) {
Steven Thomas050b2c82017-03-06 11:45:16 -0800752 std::unique_lock<std::mutex> lock(post_thread_mutex_);
Corey Tabaka2251d822017-04-20 16:04:07 -0700753 ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
754
755 // Tear down resources.
756 OnPostThreadPaused();
757
758 was_running = false;
759 post_thread_resumed_ = false;
760 post_thread_ready_.notify_all();
761
762 if (post_thread_state_ & PostThreadState::Quit) {
763 ALOGI("HardwareComposer::PostThread: Quitting.");
764 return;
Steven Thomas282a5ed2017-02-07 18:07:01 -0800765 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700766
767 post_thread_wait_.wait(lock, [this] { return !post_thread_quiescent_; });
768
769 post_thread_resumed_ = true;
770 post_thread_ready_.notify_all();
771
772 ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
Steven Thomas050b2c82017-03-06 11:45:16 -0800773 }
774
775 if (!was_running) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700776 // Setup resources.
Steven Thomas050b2c82017-03-06 11:45:16 -0800777 OnPostThreadResumed();
778 was_running = true;
Corey Tabaka2251d822017-04-20 16:04:07 -0700779
780 // Try to setup the scheduler policy if it failed during startup. Only
781 // attempt to do this on transitions from inactive to active to avoid
782 // spamming the system with RPCs and log messages.
783 if (!thread_policy_setup) {
784 thread_policy_setup =
785 SetThreadPolicy("graphics:high", "/system/performance");
786 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800787 }
788
789 int64_t vsync_timestamp = 0;
790 {
791 std::array<char, 128> buf;
792 snprintf(buf.data(), buf.size(), "wait_vsync|vsync=%d|",
793 vsync_count_ + 1);
794 ATRACE_NAME(buf.data());
795
Corey Tabaka2251d822017-04-20 16:04:07 -0700796 const int error = WaitForVSync(&vsync_timestamp);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800797 ALOGE_IF(
798 error < 0,
799 "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
800 strerror(-error));
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800801 // Don't bother processing this frame if a pause was requested
Steven Thomas050b2c82017-03-06 11:45:16 -0800802 if (error == kPostThreadInterrupted)
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800803 continue;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800804 }
805
806 ++vsync_count_;
807
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800808 if (pose_client_) {
809 // Signal the pose service with vsync info.
810 // Display timestamp is in the middle of scanout.
811 privateDvrPoseNotifyVsync(pose_client_, vsync_count_,
812 vsync_timestamp + photon_offset_ns,
813 ns_per_frame, right_eye_photon_offset_ns);
814 }
815
Corey Tabaka2251d822017-04-20 16:04:07 -0700816 const bool layer_config_changed = UpdateLayerConfig();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800817
818 // Signal all of the vsync clients. Because absolute time is used for the
819 // wakeup time below, this can take a little time if necessary.
820 if (vsync_callback_)
Corey Tabaka2251d822017-04-20 16:04:07 -0700821 vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp,
822 /*frame_time_estimate*/ 0, vsync_count_);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800823
824 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700825 // Sleep until shortly before vsync.
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800826 ATRACE_NAME("sleep");
827
Corey Tabaka2251d822017-04-20 16:04:07 -0700828 const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
829 const int64_t now_ns = GetSystemClockNs();
830 const int64_t sleep_time_ns =
831 display_time_est_ns - now_ns - kFramePostOffsetNs;
832 const int64_t wakeup_time_ns = display_time_est_ns - kFramePostOffsetNs;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800833
834 ATRACE_INT64("sleep_time_ns", sleep_time_ns);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800835 if (sleep_time_ns > 0) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700836 int error = SleepUntil(wakeup_time_ns);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800837 ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s",
838 strerror(-error));
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700839 if (error == kPostThreadInterrupted) {
840 if (layer_config_changed) {
841 // If the layer config changed we need to validateDisplay() even if
842 // we're going to drop the frame, to flush the Composer object's
843 // internal command buffer and apply our layer changes.
844 Validate(HWC_DISPLAY_PRIMARY);
845 }
Steven Thomas050b2c82017-03-06 11:45:16 -0800846 continue;
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700847 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800848 }
849 }
850
Corey Tabaka2251d822017-04-20 16:04:07 -0700851 PostLayers();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800852 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800853}
854
Corey Tabaka2251d822017-04-20 16:04:07 -0700855// Checks for changes in the surface stack and updates the layer config to
856// accomodate the new stack.
Steven Thomas050b2c82017-03-06 11:45:16 -0800857bool HardwareComposer::UpdateLayerConfig() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700858 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
Steven Thomas050b2c82017-03-06 11:45:16 -0800859 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700860 std::unique_lock<std::mutex> lock(post_thread_mutex_);
861 if (pending_surfaces_.empty())
Steven Thomas050b2c82017-03-06 11:45:16 -0800862 return false;
Corey Tabaka2251d822017-04-20 16:04:07 -0700863
864 surfaces = std::move(pending_surfaces_);
Steven Thomas050b2c82017-03-06 11:45:16 -0800865 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800866
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800867 ATRACE_NAME("UpdateLayerConfig_HwLayers");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800868
Corey Tabaka2251d822017-04-20 16:04:07 -0700869 display_surfaces_.clear();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800870
Corey Tabaka2251d822017-04-20 16:04:07 -0700871 Layer* target_layer;
872 size_t layer_index;
873 for (layer_index = 0;
874 layer_index < std::min(surfaces.size(), kMaxHardwareLayers);
875 layer_index++) {
876 // The bottom layer is opaque, other layers blend.
877 HWC::BlendMode blending =
878 layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
879 layers_[layer_index].Setup(surfaces[layer_index], blending,
880 display_transform_, HWC::Composition::Device,
881 layer_index);
882 display_surfaces_.push_back(surfaces[layer_index]);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800883 }
884
Corey Tabaka2251d822017-04-20 16:04:07 -0700885 // Clear unused layers.
886 for (size_t i = layer_index; i < kMaxHardwareLayers; i++)
887 layers_[i].Reset();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800888
Corey Tabaka2251d822017-04-20 16:04:07 -0700889 active_layer_count_ = layer_index;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800890 ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
891 active_layer_count_);
892
Corey Tabaka2251d822017-04-20 16:04:07 -0700893 // Any surfaces left over could not be assigned a hardware layer and will
894 // not be displayed.
895 ALOGW_IF(surfaces.size() != display_surfaces_.size(),
896 "HardwareComposer::UpdateLayerConfig: More surfaces than layers: "
897 "pending_surfaces=%zu display_surfaces=%zu",
898 surfaces.size(), display_surfaces_.size());
899
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800900 return true;
901}
902
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800903void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
904 vsync_callback_ = callback;
905}
906
907void HardwareComposer::HwcRefresh(hwc2_callback_data_t /*data*/,
908 hwc2_display_t /*display*/) {
909 // TODO(eieio): implement invalidate callbacks.
910}
911
912void HardwareComposer::HwcVSync(hwc2_callback_data_t /*data*/,
913 hwc2_display_t /*display*/,
914 int64_t /*timestamp*/) {
915 ATRACE_NAME(__PRETTY_FUNCTION__);
916 // Intentionally empty. HWC may require a callback to be set to enable vsync
917 // signals. We bypass this callback thread by monitoring the vsync event
918 // directly, but signals still need to be enabled.
919}
920
921void HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/,
922 hwc2_display_t /*display*/,
923 hwc2_connection_t /*connected*/) {
924 // TODO(eieio): implement display hotplug callbacks.
925}
926
Steven Thomas3cfac282017-02-06 12:29:30 -0800927void HardwareComposer::OnHardwareComposerRefresh() {
928 // TODO(steventhomas): Handle refresh.
929}
930
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800931void HardwareComposer::SetBacklightBrightness(int brightness) {
932 if (backlight_brightness_fd_) {
933 std::array<char, 32> text;
934 const int length = snprintf(text.data(), text.size(), "%d", brightness);
935 write(backlight_brightness_fd_.Get(), text.data(), length);
936 }
937}
938
Corey Tabaka2251d822017-04-20 16:04:07 -0700939void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
940 const HWCDisplayMetrics* metrics) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800941 hwc2_hidl_ = hwc2_hidl;
942 display_metrics_ = metrics;
943}
944
945void Layer::Reset() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800946 if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
947 hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
948 hardware_composer_layer_ = 0;
949 }
950
Corey Tabaka2251d822017-04-20 16:04:07 -0700951 z_order_ = 0;
952 blending_ = HWC::BlendMode::None;
953 transform_ = HWC::Transform::None;
954 composition_type_ = HWC::Composition::Invalid;
955 target_composition_type_ = composition_type_;
956 source_ = EmptyVariant{};
957 acquire_fence_.Close();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800958 surface_rect_functions_applied_ = false;
959}
960
Corey Tabaka2251d822017-04-20 16:04:07 -0700961void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
962 HWC::BlendMode blending, HWC::Transform transform,
963 HWC::Composition composition_type, size_t z_order) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800964 Reset();
Corey Tabaka2251d822017-04-20 16:04:07 -0700965 z_order_ = z_order;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800966 blending_ = blending;
967 transform_ = transform;
Corey Tabaka2251d822017-04-20 16:04:07 -0700968 composition_type_ = HWC::Composition::Invalid;
969 target_composition_type_ = composition_type;
970 source_ = SourceSurface{surface};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800971 CommonLayerSetup();
972}
973
974void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
Corey Tabaka2251d822017-04-20 16:04:07 -0700975 HWC::BlendMode blending, HWC::Transform transform,
976 HWC::Composition composition_type, size_t z_order) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800977 Reset();
Corey Tabaka2251d822017-04-20 16:04:07 -0700978 z_order_ = z_order;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800979 blending_ = blending;
980 transform_ = transform;
Corey Tabaka2251d822017-04-20 16:04:07 -0700981 composition_type_ = HWC::Composition::Invalid;
982 target_composition_type_ = composition_type;
983 source_ = SourceBuffer{buffer};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800984 CommonLayerSetup();
985}
986
Corey Tabaka2251d822017-04-20 16:04:07 -0700987void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
988 if (source_.is<SourceBuffer>())
989 std::get<SourceBuffer>(source_) = {buffer};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800990}
991
Corey Tabaka2251d822017-04-20 16:04:07 -0700992void Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; }
993void Layer::SetZOrder(size_t z_order) { z_order_ = z_order; }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800994
995IonBuffer* Layer::GetBuffer() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700996 struct Visitor {
997 IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
998 IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
999 IonBuffer* operator()(EmptyVariant) { return nullptr; }
1000 };
1001 return source_.Visit(Visitor{});
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001002}
1003
1004void Layer::UpdateLayerSettings() {
1005 if (!IsLayerSetup()) {
Corey Tabaka2251d822017-04-20 16:04:07 -07001006 ALOGE(
1007 "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
1008 "unused Layer!");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001009 return;
1010 }
1011
Corey Tabaka2251d822017-04-20 16:04:07 -07001012 HWC::Error error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001013 hwc2_display_t display = HWC_DISPLAY_PRIMARY;
1014
Corey Tabaka2251d822017-04-20 16:04:07 -07001015 error = hwc2_hidl_->setLayerCompositionType(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001016 display, hardware_composer_layer_,
Corey Tabaka2251d822017-04-20 16:04:07 -07001017 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1018 ALOGE_IF(
1019 error != HWC::Error::None,
1020 "Layer::UpdateLayerSettings: Error setting layer composition type: %s",
1021 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001022
Corey Tabaka2251d822017-04-20 16:04:07 -07001023 error = hwc2_hidl_->setLayerBlendMode(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001024 display, hardware_composer_layer_,
Corey Tabaka2251d822017-04-20 16:04:07 -07001025 blending_.cast<Hwc2::IComposerClient::BlendMode>());
1026 ALOGE_IF(error != HWC::Error::None,
1027 "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
1028 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001029
Corey Tabaka2251d822017-04-20 16:04:07 -07001030 // TODO(eieio): Use surface attributes or some other mechanism to control
1031 // the layer display frame.
1032 error = hwc2_hidl_->setLayerDisplayFrame(
1033 display, hardware_composer_layer_,
1034 {0, 0, display_metrics_->width, display_metrics_->height});
1035 ALOGE_IF(error != HWC::Error::None,
1036 "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
1037 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001038
Corey Tabaka2251d822017-04-20 16:04:07 -07001039 error = hwc2_hidl_->setLayerVisibleRegion(
1040 display, hardware_composer_layer_,
1041 {{0, 0, display_metrics_->width, display_metrics_->height}});
1042 ALOGE_IF(error != HWC::Error::None,
1043 "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
1044 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001045
Corey Tabaka2251d822017-04-20 16:04:07 -07001046 error =
1047 hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
1048 ALOGE_IF(error != HWC::Error::None,
1049 "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
1050 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001051
Corey Tabaka2251d822017-04-20 16:04:07 -07001052 error =
1053 hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
1054 ALOGE_IF(error != HWC::Error::None,
1055 "Layer::UpdateLayerSettings: Error setting z_ order: %s",
1056 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001057}
1058
1059void Layer::CommonLayerSetup() {
Corey Tabaka2251d822017-04-20 16:04:07 -07001060 HWC::Error error =
1061 hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
1062 ALOGE_IF(
1063 error != HWC::Error::None,
1064 "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
1065 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001066 UpdateLayerSettings();
1067}
1068
1069void Layer::Prepare() {
1070 int right, bottom;
Daniel Nicoara1f42e3a2017-04-10 13:27:32 -04001071 sp<GraphicBuffer> handle;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001072
Corey Tabaka2251d822017-04-20 16:04:07 -07001073 // Acquire the next buffer according to the type of source.
1074 IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
1075 std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
1076 });
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001077
Corey Tabaka2251d822017-04-20 16:04:07 -07001078 // When a layer is first setup there may be some time before the first buffer
1079 // arrives. Setup the HWC layer as a solid color to stall for time until the
1080 // first buffer arrives. Once the first buffer arrives there will always be a
1081 // buffer for the frame even if it is old.
1082 if (!handle.get()) {
1083 if (composition_type_ == HWC::Composition::Invalid) {
1084 composition_type_ = HWC::Composition::SolidColor;
1085 hwc2_hidl_->setLayerCompositionType(
1086 HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1087 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1088 Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
1089 hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1090 layer_color);
1091 } else {
1092 // The composition type is already set. Nothing else to do until a
1093 // buffer arrives.
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001094 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001095 } else {
Corey Tabaka2251d822017-04-20 16:04:07 -07001096 if (composition_type_ != target_composition_type_) {
1097 composition_type_ = target_composition_type_;
1098 hwc2_hidl_->setLayerCompositionType(
1099 HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1100 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1101 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001102
Corey Tabaka2251d822017-04-20 16:04:07 -07001103 HWC::Error error{HWC::Error::None};
1104 error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
1105 hardware_composer_layer_, 0, handle,
1106 acquire_fence_.Get());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001107
Corey Tabaka2251d822017-04-20 16:04:07 -07001108 ALOGE_IF(error != HWC::Error::None,
1109 "Layer::Prepare: Error setting layer buffer: %s",
1110 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001111
Corey Tabaka2251d822017-04-20 16:04:07 -07001112 if (!surface_rect_functions_applied_) {
1113 const float float_right = right;
1114 const float float_bottom = bottom;
1115 error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
1116 hardware_composer_layer_,
1117 {0, 0, float_right, float_bottom});
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001118
Corey Tabaka2251d822017-04-20 16:04:07 -07001119 ALOGE_IF(error != HWC::Error::None,
1120 "Layer::Prepare: Error setting layer source crop: %s",
1121 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001122
Corey Tabaka2251d822017-04-20 16:04:07 -07001123 surface_rect_functions_applied_ = true;
1124 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001125 }
1126}
1127
1128void Layer::Finish(int release_fence_fd) {
Corey Tabaka2251d822017-04-20 16:04:07 -07001129 IfAnyOf<SourceSurface, SourceBuffer>::Call(
1130 &source_, [release_fence_fd](auto& source) {
1131 source.Finish(LocalHandle(release_fence_fd));
1132 });
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001133}
1134
Corey Tabaka2251d822017-04-20 16:04:07 -07001135void Layer::Drop() { acquire_fence_.Close(); }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001136
1137} // namespace dvr
1138} // namespace android