blob: 34474d969a1f307ad80c6107cc50939af377875f [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>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080028
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080029using android::pdx::LocalHandle;
Corey Tabaka2251d822017-04-20 16:04:07 -070030using android::pdx::rpc::EmptyVariant;
31using android::pdx::rpc::IfAnyOf;
32
33using namespace std::chrono_literals;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080034
35namespace android {
36namespace dvr {
37
38namespace {
39
40// If the number of pending fences goes over this count at the point when we
41// are about to submit a new frame to HWC, we will drop the frame. This should
42// be a signal that the display driver has begun queuing frames. Note that with
43// smart displays (with RAM), the fence is signaled earlier than the next vsync,
44// at the point when the DMA to the display completes. Currently we use a smart
45// display and the EDS timing coincides with zero pending fences, so this is 0.
46constexpr int kAllowedPendingFenceCount = 0;
47
Corey Tabaka2251d822017-04-20 16:04:07 -070048// Offset before vsync to submit frames to hardware composer.
49constexpr int64_t kFramePostOffsetNs = 4000000; // 4ms
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080050
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080051const char kBacklightBrightnessSysFile[] =
52 "/sys/class/leds/lcd-backlight/brightness";
53
54const char kPrimaryDisplayVSyncEventFile[] =
55 "/sys/class/graphics/fb0/vsync_event";
56
57const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
58
59const char kDvrPerformanceProperty[] = "sys.dvr.performance";
60
Luke Song4b788322017-03-24 14:17:31 -070061const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080062
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080063// Get time offset from a vsync to when the pose for that vsync should be
64// predicted out to. For example, if scanout gets halfway through the frame
65// at the halfway point between vsyncs, then this could be half the period.
66// With global shutter displays, this should be changed to the offset to when
67// illumination begins. Low persistence adds a frame of latency, so we predict
68// to the center of the next frame.
69inline int64_t GetPosePredictionTimeOffset(int64_t vsync_period_ns) {
70 return (vsync_period_ns * 150) / 100;
71}
72
Corey Tabaka2251d822017-04-20 16:04:07 -070073// Attempts to set the scheduler class and partiton for the current thread.
74// Returns true on success or false on failure.
75bool SetThreadPolicy(const std::string& scheduler_class,
76 const std::string& partition) {
77 int error = dvrSetSchedulerClass(0, scheduler_class.c_str());
78 if (error < 0) {
79 ALOGE(
80 "SetThreadPolicy: Failed to set scheduler class \"%s\" for "
81 "thread_id=%d: %s",
82 scheduler_class.c_str(), gettid(), strerror(-error));
83 return false;
84 }
85 error = dvrSetCpuPartition(0, partition.c_str());
86 if (error < 0) {
87 ALOGE(
88 "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: "
89 "%s",
90 partition.c_str(), gettid(), strerror(-error));
91 return false;
92 }
93 return true;
94}
95
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080096} // anonymous namespace
97
Corey Tabaka2251d822017-04-20 16:04:07 -070098// Layer static data.
99Hwc2::Composer* Layer::hwc2_hidl_;
100const HWCDisplayMetrics* Layer::display_metrics_;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800101
Corey Tabaka2251d822017-04-20 16:04:07 -0700102// HardwareComposer static data;
103constexpr size_t HardwareComposer::kMaxHardwareLayers;
104
105HardwareComposer::HardwareComposer()
106 : HardwareComposer(nullptr, RequestDisplayCallback()) {}
107
108HardwareComposer::HardwareComposer(
109 Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800110 : initialized_(false),
111 hwc2_hidl_(hwc2_hidl),
Corey Tabaka2251d822017-04-20 16:04:07 -0700112 request_display_callback_(request_display_callback),
113 callbacks_(new ComposerCallback) {}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800114
115HardwareComposer::~HardwareComposer(void) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700116 UpdatePostThreadState(PostThreadState::Quit, true);
117 if (post_thread_.joinable())
Steven Thomas050b2c82017-03-06 11:45:16 -0800118 post_thread_.join();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800119}
120
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800121bool HardwareComposer::Initialize() {
122 if (initialized_) {
123 ALOGE("HardwareComposer::Initialize: already initialized.");
124 return false;
125 }
126
Corey Tabaka2251d822017-04-20 16:04:07 -0700127 HWC::Error error = HWC::Error::None;
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800128
129 Hwc2::Config config;
Corey Tabaka2251d822017-04-20 16:04:07 -0700130 error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800131
Corey Tabaka2251d822017-04-20 16:04:07 -0700132 if (error != HWC::Error::None) {
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800133 ALOGE("HardwareComposer: Failed to get current display config : %d",
134 config);
135 return false;
136 }
137
Corey Tabaka2251d822017-04-20 16:04:07 -0700138 error =
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800139 GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
140
Corey Tabaka2251d822017-04-20 16:04:07 -0700141 if (error != HWC::Error::None) {
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800142 ALOGE(
143 "HardwareComposer: Failed to get display attributes for current "
144 "configuration : %d",
Corey Tabaka2251d822017-04-20 16:04:07 -0700145 error.value);
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800146 return false;
147 }
148
149 ALOGI(
150 "HardwareComposer: primary display attributes: width=%d height=%d "
151 "vsync_period_ns=%d DPI=%dx%d",
152 native_display_metrics_.width, native_display_metrics_.height,
153 native_display_metrics_.vsync_period_ns, native_display_metrics_.dpi.x,
154 native_display_metrics_.dpi.y);
155
156 // Set the display metrics but never use rotation to avoid the long latency of
157 // rotation processing in hwc.
158 display_transform_ = HWC_TRANSFORM_NONE;
159 display_metrics_ = native_display_metrics_;
160
Corey Tabaka2251d822017-04-20 16:04:07 -0700161 // Pass hwc instance and metrics to setup globals for Layer.
162 Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
163
164 post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
Steven Thomas050b2c82017-03-06 11:45:16 -0800165 LOG_ALWAYS_FATAL_IF(
Corey Tabaka2251d822017-04-20 16:04:07 -0700166 !post_thread_event_fd_,
Steven Thomas050b2c82017-03-06 11:45:16 -0800167 "HardwareComposer: Failed to create interrupt event fd : %s",
168 strerror(errno));
169
170 post_thread_ = std::thread(&HardwareComposer::PostThread, this);
171
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800172 initialized_ = true;
173
174 return initialized_;
175}
176
Steven Thomas050b2c82017-03-06 11:45:16 -0800177void HardwareComposer::Enable() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700178 UpdatePostThreadState(PostThreadState::Suspended, false);
Steven Thomas050b2c82017-03-06 11:45:16 -0800179}
180
181void HardwareComposer::Disable() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700182 UpdatePostThreadState(PostThreadState::Suspended, true);
Steven Thomas050b2c82017-03-06 11:45:16 -0800183}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800184
Corey Tabaka2251d822017-04-20 16:04:07 -0700185// Update the post thread quiescent state based on idle and suspended inputs.
186void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
187 bool suspend) {
188 std::unique_lock<std::mutex> lock(post_thread_mutex_);
189
190 // Update the votes in the state variable before evaluating the effective
191 // quiescent state. Any bits set in post_thread_state_ indicate that the post
192 // thread should be suspended.
193 if (suspend) {
194 post_thread_state_ |= state;
195 } else {
196 post_thread_state_ &= ~state;
197 }
198
199 const bool quit = post_thread_state_ & PostThreadState::Quit;
200 const bool effective_suspend = post_thread_state_ != PostThreadState::Active;
201 if (quit) {
202 post_thread_quiescent_ = true;
203 eventfd_write(post_thread_event_fd_.Get(), 1);
204 post_thread_wait_.notify_one();
205 } else if (effective_suspend && !post_thread_quiescent_) {
206 post_thread_quiescent_ = true;
207 eventfd_write(post_thread_event_fd_.Get(), 1);
208 } else if (!effective_suspend && post_thread_quiescent_) {
209 post_thread_quiescent_ = false;
210 eventfd_t value;
211 eventfd_read(post_thread_event_fd_.Get(), &value);
212 post_thread_wait_.notify_one();
213 }
214
215 // Wait until the post thread is in the requested state.
216 post_thread_ready_.wait(lock, [this, effective_suspend] {
217 return effective_suspend != post_thread_resumed_;
218 });
Steven Thomas050b2c82017-03-06 11:45:16 -0800219}
Steven Thomas282a5ed2017-02-07 18:07:01 -0800220
Steven Thomas050b2c82017-03-06 11:45:16 -0800221void HardwareComposer::OnPostThreadResumed() {
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700222 hwc2_hidl_->resetCommands();
223
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800224 // Connect to pose service.
225 pose_client_ = dvrPoseCreate();
226 ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
227
Corey Tabaka2251d822017-04-20 16:04:07 -0700228 // HIDL HWC seems to have an internal race condition. If we submit a frame too
229 // soon after turning on VSync we don't get any VSync signals. Give poor HWC
230 // implementations a chance to enable VSync before we continue.
231 EnableVsync(false);
232 std::this_thread::sleep_for(100ms);
Steven Thomas050b2c82017-03-06 11:45:16 -0800233 EnableVsync(true);
Corey Tabaka2251d822017-04-20 16:04:07 -0700234 std::this_thread::sleep_for(100ms);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800235
Steven Thomas050b2c82017-03-06 11:45:16 -0800236 // TODO(skiazyk): We need to do something about accessing this directly,
237 // supposedly there is a backlight service on the way.
238 // TODO(steventhomas): When we change the backlight setting, will surface
239 // flinger (or something else) set it back to its original value once we give
240 // control of the display back to surface flinger?
241 SetBacklightBrightness(255);
Steven Thomas282a5ed2017-02-07 18:07:01 -0800242
Steven Thomas050b2c82017-03-06 11:45:16 -0800243 // Trigger target-specific performance mode change.
244 property_set(kDvrPerformanceProperty, "performance");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800245}
246
Steven Thomas050b2c82017-03-06 11:45:16 -0800247void HardwareComposer::OnPostThreadPaused() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700248 retire_fence_fds_.clear();
Steven Thomas050b2c82017-03-06 11:45:16 -0800249 display_surfaces_.clear();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800250
Corey Tabaka2251d822017-04-20 16:04:07 -0700251 for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
252 layers_[i].Reset();
253 }
254 active_layer_count_ = 0;
Steven Thomas050b2c82017-03-06 11:45:16 -0800255
256 if (pose_client_) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800257 dvrPoseDestroy(pose_client_);
Steven Thomas050b2c82017-03-06 11:45:16 -0800258 pose_client_ = nullptr;
259 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800260
Steven Thomas050b2c82017-03-06 11:45:16 -0800261 EnableVsync(false);
262
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700263 hwc2_hidl_->resetCommands();
264
Steven Thomas050b2c82017-03-06 11:45:16 -0800265 // Trigger target-specific performance mode change.
266 property_set(kDvrPerformanceProperty, "idle");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800267}
268
Corey Tabaka2251d822017-04-20 16:04:07 -0700269HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800270 uint32_t num_types;
271 uint32_t num_requests;
Corey Tabaka2251d822017-04-20 16:04:07 -0700272 HWC::Error error =
273 hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800274
275 if (error == HWC2_ERROR_HAS_CHANGES) {
276 // TODO(skiazyk): We might need to inspect the requested changes first, but
277 // so far it seems like we shouldn't ever hit a bad state.
278 // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
279 // display);
Corey Tabaka2251d822017-04-20 16:04:07 -0700280 error = hwc2_hidl_->acceptDisplayChanges(display);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800281 }
282
283 return error;
284}
285
286int32_t HardwareComposer::EnableVsync(bool enabled) {
287 return (int32_t)hwc2_hidl_->setVsyncEnabled(
288 HWC_DISPLAY_PRIMARY,
289 (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
290 : HWC2_VSYNC_DISABLE));
291}
292
Corey Tabaka2251d822017-04-20 16:04:07 -0700293HWC::Error HardwareComposer::Present(hwc2_display_t display) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800294 int32_t present_fence;
Corey Tabaka2251d822017-04-20 16:04:07 -0700295 HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800296
297 // According to the documentation, this fence is signaled at the time of
298 // vsync/DMA for physical displays.
Corey Tabaka2251d822017-04-20 16:04:07 -0700299 if (error == HWC::Error::None) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800300 ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
301 retire_fence_fds_.emplace_back(present_fence);
302 } else {
303 ATRACE_INT("HardwareComposer: PresentResult", error);
304 }
305
306 return error;
307}
308
Corey Tabaka2251d822017-04-20 16:04:07 -0700309HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
310 hwc2_config_t config,
311 hwc2_attribute_t attribute,
312 int32_t* out_value) const {
313 return hwc2_hidl_->getDisplayAttribute(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800314 display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
315}
316
Corey Tabaka2251d822017-04-20 16:04:07 -0700317HWC::Error HardwareComposer::GetDisplayMetrics(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800318 hwc2_display_t display, hwc2_config_t config,
319 HWCDisplayMetrics* out_metrics) const {
Corey Tabaka2251d822017-04-20 16:04:07 -0700320 HWC::Error error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800321
Corey Tabaka2251d822017-04-20 16:04:07 -0700322 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
323 &out_metrics->width);
324 if (error != HWC::Error::None) {
325 ALOGE(
326 "HardwareComposer::GetDisplayMetrics: Failed to get display width: %s",
327 error.to_string().c_str());
328 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800329 }
330
Corey Tabaka2251d822017-04-20 16:04:07 -0700331 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
332 &out_metrics->height);
333 if (error != HWC::Error::None) {
334 ALOGE(
335 "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
336 error.to_string().c_str());
337 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800338 }
339
Corey Tabaka2251d822017-04-20 16:04:07 -0700340 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
341 &out_metrics->vsync_period_ns);
342 if (error != HWC::Error::None) {
343 ALOGE(
344 "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
345 error.to_string().c_str());
346 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800347 }
348
Corey Tabaka2251d822017-04-20 16:04:07 -0700349 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
350 &out_metrics->dpi.x);
351 if (error != HWC::Error::None) {
352 ALOGE(
353 "HardwareComposer::GetDisplayMetrics: Failed to get display DPI X: %s",
354 error.to_string().c_str());
355 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800356 }
357
Corey Tabaka2251d822017-04-20 16:04:07 -0700358 error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
359 &out_metrics->dpi.y);
360 if (error != HWC::Error::None) {
361 ALOGE(
362 "HardwareComposer::GetDisplayMetrics: Failed to get display DPI Y: %s",
363 error.to_string().c_str());
364 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800365 }
366
Corey Tabaka2251d822017-04-20 16:04:07 -0700367 return HWC::Error::None;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800368}
369
Corey Tabaka2251d822017-04-20 16:04:07 -0700370std::string HardwareComposer::Dump() { return hwc2_hidl_->dumpDebugInfo(); }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800371
Corey Tabaka2251d822017-04-20 16:04:07 -0700372void HardwareComposer::PostLayers() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800373 ATRACE_NAME("HardwareComposer::PostLayers");
374
375 // Setup the hardware composer layers with current buffers.
376 for (size_t i = 0; i < active_layer_count_; i++) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700377 layers_[i].Prepare();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800378 }
379
Corey Tabaka2251d822017-04-20 16:04:07 -0700380 HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
381 if (error != HWC::Error::None) {
382 ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
383 error.to_string().c_str());
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700384 return;
385 }
386
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800387 // Now that we have taken in a frame from the application, we have a chance
388 // to drop the frame before passing the frame along to HWC.
389 // If the display driver has become backed up, we detect it here and then
390 // react by skipping this frame to catch up latency.
391 while (!retire_fence_fds_.empty() &&
392 (!retire_fence_fds_.front() ||
393 sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) {
394 // There are only 2 fences in here, no performance problem to shift the
395 // array of ints.
396 retire_fence_fds_.erase(retire_fence_fds_.begin());
397 }
398
399 const bool is_frame_pending = IsFramePendingInDriver();
400 const bool is_fence_pending =
401 retire_fence_fds_.size() > kAllowedPendingFenceCount;
402
403 if (is_fence_pending || is_frame_pending) {
404 ATRACE_INT("frame_skip_count", ++frame_skip_count_);
405
406 ALOGW_IF(is_frame_pending, "Warning: frame already queued, dropping frame");
407 ALOGW_IF(is_fence_pending,
408 "Warning: dropping a frame to catch up with HWC (pending = %zd)",
409 retire_fence_fds_.size());
410
411 for (size_t i = 0; i < active_layer_count_; i++) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700412 layers_[i].Drop();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800413 }
414 return;
415 } else {
416 // Make the transition more obvious in systrace when the frame skip happens
417 // above.
418 ATRACE_INT("frame_skip_count", 0);
419 }
420
421#if TRACE
422 for (size_t i = 0; i < active_layer_count_; i++)
Corey Tabaka2251d822017-04-20 16:04:07 -0700423 ALOGI("HardwareComposer::PostLayers: layer=%zu composition=%s", i,
424 layers_[i].GetCompositionType().to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800425#endif
426
Corey Tabaka2251d822017-04-20 16:04:07 -0700427 error = Present(HWC_DISPLAY_PRIMARY);
428 if (error != HWC::Error::None) {
429 ALOGE("HardwareComposer::PostLayers: Present failed: %s",
430 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800431 return;
432 }
433
434 std::vector<Hwc2::Layer> out_layers;
435 std::vector<int> out_fences;
Corey Tabaka2251d822017-04-20 16:04:07 -0700436 error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
437 &out_fences);
438 ALOGE_IF(error != HWC::Error::None,
439 "HardwareComposer::PostLayers: Failed to get release fences: %s",
440 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800441
442 // Perform post-frame bookkeeping. Unused layers are a no-op.
Corey Tabaka2251d822017-04-20 16:04:07 -0700443 uint32_t num_elements = out_layers.size();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800444 for (size_t i = 0; i < num_elements; ++i) {
445 for (size_t j = 0; j < active_layer_count_; ++j) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700446 if (layers_[j].GetLayerHandle() == out_layers[i]) {
447 layers_[j].Finish(out_fences[i]);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800448 }
449 }
450 }
451}
452
Steven Thomas050b2c82017-03-06 11:45:16 -0800453void HardwareComposer::SetDisplaySurfaces(
Corey Tabaka2251d822017-04-20 16:04:07 -0700454 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
Jin Qian7480c062017-03-21 00:04:15 +0000455 ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
456 surfaces.size());
Corey Tabaka2251d822017-04-20 16:04:07 -0700457 const bool display_idle = surfaces.size() == 0;
458 {
459 std::unique_lock<std::mutex> lock(post_thread_mutex_);
460 pending_surfaces_ = std::move(surfaces);
461 }
462
463 // Set idle state based on whether there are any surfaces to handle.
464 UpdatePostThreadState(PostThreadState::Idle, display_idle);
465
466 // XXX: TEMPORARY
467 // Request control of the display based on whether there are any surfaces to
468 // handle. This callback sets the post thread active state once the transition
469 // is complete in SurfaceFlinger.
470 // TODO(eieio): Unify the control signal used to move SurfaceFlinger into VR
471 // mode. Currently this is hooked up to persistent VR mode, but perhaps this
472 // makes more sense to control it from VrCore, which could in turn base its
473 // decision on persistent VR mode.
474 if (request_display_callback_)
475 request_display_callback_(!display_idle);
Steven Thomas050b2c82017-03-06 11:45:16 -0800476}
Jin Qian7480c062017-03-21 00:04:15 +0000477
Corey Tabaka2251d822017-04-20 16:04:07 -0700478int HardwareComposer::PostThreadPollInterruptible(
479 const pdx::LocalHandle& event_fd, int requested_events) {
Steven Thomas050b2c82017-03-06 11:45:16 -0800480 pollfd pfd[2] = {
481 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700482 .fd = event_fd.Get(),
Steven Thomas66747c12017-03-22 18:45:31 -0700483 .events = static_cast<short>(requested_events),
484 .revents = 0,
Steven Thomas050b2c82017-03-06 11:45:16 -0800485 },
486 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700487 .fd = post_thread_event_fd_.Get(),
Steven Thomas050b2c82017-03-06 11:45:16 -0800488 .events = POLLPRI | POLLIN,
489 .revents = 0,
490 },
491 };
492 int ret, error;
493 do {
494 ret = poll(pfd, 2, -1);
495 error = errno;
496 ALOGW_IF(ret < 0,
497 "HardwareComposer::PostThreadPollInterruptible: Error during "
498 "poll(): %s (%d)",
499 strerror(error), error);
500 } while (ret < 0 && error == EINTR);
501
502 if (ret < 0) {
503 return -error;
504 } else if (pfd[0].revents != 0) {
505 return 0;
506 } else if (pfd[1].revents != 0) {
507 ALOGI("VrHwcPost thread interrupted");
508 return kPostThreadInterrupted;
509 } else {
510 return 0;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800511 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800512}
513
514// Reads the value of the display driver wait_pingpong state. Returns 0 or 1
515// (the value of the state) on success or a negative error otherwise.
516// TODO(eieio): This is pretty driver specific, this should be moved to a
517// separate class eventually.
518int HardwareComposer::ReadWaitPPState() {
519 // Gracefully handle when the kernel does not support this feature.
520 if (!primary_display_wait_pp_fd_)
521 return 0;
522
523 const int wait_pp_fd = primary_display_wait_pp_fd_.Get();
524 int ret, error;
525
526 ret = lseek(wait_pp_fd, 0, SEEK_SET);
527 if (ret < 0) {
528 error = errno;
529 ALOGE("HardwareComposer::ReadWaitPPState: Failed to seek wait_pp fd: %s",
530 strerror(error));
531 return -error;
532 }
533
534 char data = -1;
535 ret = read(wait_pp_fd, &data, sizeof(data));
536 if (ret < 0) {
537 error = errno;
538 ALOGE("HardwareComposer::ReadWaitPPState: Failed to read wait_pp state: %s",
539 strerror(error));
540 return -error;
541 }
542
543 switch (data) {
544 case '0':
545 return 0;
546 case '1':
547 return 1;
548 default:
549 ALOGE(
550 "HardwareComposer::ReadWaitPPState: Unexpected value for wait_pp: %d",
551 data);
552 return -EINVAL;
553 }
554}
555
556// Reads the timestamp of the last vsync from the display driver.
557// TODO(eieio): This is pretty driver specific, this should be moved to a
558// separate class eventually.
559int HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) {
560 const int event_fd = primary_display_vsync_event_fd_.Get();
561 int ret, error;
562
563 // The driver returns data in the form "VSYNC=<timestamp ns>".
564 std::array<char, 32> data;
565 data.fill('\0');
566
567 // Seek back to the beginning of the event file.
568 ret = lseek(event_fd, 0, SEEK_SET);
569 if (ret < 0) {
570 error = errno;
571 ALOGE(
572 "HardwareComposer::ReadVSyncTimestamp: Failed to seek vsync event fd: "
573 "%s",
574 strerror(error));
575 return -error;
576 }
577
578 // Read the vsync event timestamp.
579 ret = read(event_fd, data.data(), data.size());
580 if (ret < 0) {
581 error = errno;
582 ALOGE_IF(
583 error != EAGAIN,
584 "HardwareComposer::ReadVSyncTimestamp: Error while reading timestamp: "
585 "%s",
586 strerror(error));
587 return -error;
588 }
589
590 ret = sscanf(data.data(), "VSYNC=%" PRIu64,
591 reinterpret_cast<uint64_t*>(timestamp));
592 if (ret < 0) {
593 error = errno;
594 ALOGE(
595 "HardwareComposer::ReadVSyncTimestamp: Error while parsing timestamp: "
596 "%s",
597 strerror(error));
598 return -error;
599 }
600
601 return 0;
602}
603
604// Blocks until the next vsync event is signaled by the display driver.
605// TODO(eieio): This is pretty driver specific, this should be moved to a
606// separate class eventually.
Steven Thomas050b2c82017-03-06 11:45:16 -0800607int HardwareComposer::BlockUntilVSync() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700608 // Vsync is signaled by POLLPRI on the fb vsync node.
609 return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800610}
611
612// Waits for the next vsync and returns the timestamp of the vsync event. If
613// vsync already passed since the last call, returns the latest vsync timestamp
614// instead of blocking. This method updates the last_vsync_timeout_ in the
615// process.
616//
617// TODO(eieio): This is pretty driver specific, this should be moved to a
618// separate class eventually.
619int HardwareComposer::WaitForVSync(int64_t* timestamp) {
620 int error;
621
622 // Get the current timestamp and decide what to do.
623 while (true) {
624 int64_t current_vsync_timestamp;
625 error = ReadVSyncTimestamp(&current_vsync_timestamp);
626 if (error < 0 && error != -EAGAIN)
627 return error;
628
629 if (error == -EAGAIN) {
630 // Vsync was turned off, wait for the next vsync event.
Steven Thomas050b2c82017-03-06 11:45:16 -0800631 error = BlockUntilVSync();
632 if (error < 0 || error == kPostThreadInterrupted)
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800633 return error;
634
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800635 // Try again to get the timestamp for this new vsync interval.
636 continue;
637 }
638
639 // Check that we advanced to a later vsync interval.
640 if (TimestampGT(current_vsync_timestamp, last_vsync_timestamp_)) {
641 *timestamp = last_vsync_timestamp_ = current_vsync_timestamp;
642 return 0;
643 }
644
645 // See how close we are to the next expected vsync. If we're within 1ms,
646 // sleep for 1ms and try again.
647 const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
Corey Tabaka2251d822017-04-20 16:04:07 -0700648 const int64_t threshold_ns = 1000000; // 1ms
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800649
650 const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
651 const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
652
653 if (distance_to_vsync_est > threshold_ns) {
654 // Wait for vsync event notification.
Steven Thomas050b2c82017-03-06 11:45:16 -0800655 error = BlockUntilVSync();
656 if (error < 0 || error == kPostThreadInterrupted)
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800657 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800658 } else {
Steven Thomas050b2c82017-03-06 11:45:16 -0800659 // Sleep for a short time (1 millisecond) before retrying.
Corey Tabaka2251d822017-04-20 16:04:07 -0700660 error = SleepUntil(GetSystemClockNs() + threshold_ns);
Steven Thomas050b2c82017-03-06 11:45:16 -0800661 if (error < 0 || error == kPostThreadInterrupted)
662 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800663 }
664 }
665}
666
667int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
668 const int timer_fd = vsync_sleep_timer_fd_.Get();
669 const itimerspec wakeup_itimerspec = {
670 .it_interval = {.tv_sec = 0, .tv_nsec = 0},
671 .it_value = NsToTimespec(wakeup_timestamp),
672 };
673 int ret =
674 timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr);
675 int error = errno;
676 if (ret < 0) {
677 ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s",
678 strerror(error));
679 return -error;
680 }
681
Corey Tabaka2251d822017-04-20 16:04:07 -0700682 return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800683}
684
685void HardwareComposer::PostThread() {
686 // NOLINTNEXTLINE(runtime/int)
Steven Thomas050b2c82017-03-06 11:45:16 -0800687 prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800688
Corey Tabaka2251d822017-04-20 16:04:07 -0700689 // Set the scheduler to SCHED_FIFO with high priority. If this fails here
690 // there may have been a startup timing issue between this thread and
691 // performanced. Try again later when this thread becomes active.
692 bool thread_policy_setup =
693 SetThreadPolicy("graphics:high", "/system/performance");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800694
Steven Thomas050b2c82017-03-06 11:45:16 -0800695#if ENABLE_BACKLIGHT_BRIGHTNESS
696 // TODO(hendrikw): This isn't required at the moment. It's possible that there
697 // is another method to access this when needed.
698 // Open the backlight brightness control sysfs node.
699 backlight_brightness_fd_ = LocalHandle(kBacklightBrightnessSysFile, O_RDWR);
700 ALOGW_IF(!backlight_brightness_fd_,
701 "HardwareComposer: Failed to open backlight brightness control: %s",
702 strerror(errno));
Corey Tabaka2251d822017-04-20 16:04:07 -0700703#endif // ENABLE_BACKLIGHT_BRIGHTNESS
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800704
Steven Thomas050b2c82017-03-06 11:45:16 -0800705 // Open the vsync event node for the primary display.
706 // TODO(eieio): Move this into a platform-specific class.
707 primary_display_vsync_event_fd_ =
708 LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY);
709 ALOGE_IF(!primary_display_vsync_event_fd_,
710 "HardwareComposer: Failed to open vsync event node for primary "
711 "display: %s",
712 strerror(errno));
713
714 // Open the wait pingpong status node for the primary display.
715 // TODO(eieio): Move this into a platform-specific class.
716 primary_display_wait_pp_fd_ =
717 LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY);
718 ALOGW_IF(
719 !primary_display_wait_pp_fd_,
720 "HardwareComposer: Failed to open wait_pp node for primary display: %s",
721 strerror(errno));
722
723 // Create a timerfd based on CLOCK_MONOTINIC.
724 vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
725 LOG_ALWAYS_FATAL_IF(
726 !vsync_sleep_timer_fd_,
727 "HardwareComposer: Failed to create vsync sleep timerfd: %s",
728 strerror(errno));
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800729
730 const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
731 const int64_t photon_offset_ns = GetPosePredictionTimeOffset(ns_per_frame);
732
733 // TODO(jbates) Query vblank time from device, when such an API is available.
734 // This value (6.3%) was measured on A00 in low persistence mode.
735 int64_t vblank_ns = ns_per_frame * 63 / 1000;
736 int64_t right_eye_photon_offset_ns = (ns_per_frame - vblank_ns) / 2;
737
738 // Check property for overriding right eye offset value.
739 right_eye_photon_offset_ns =
740 property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
741
Steven Thomas050b2c82017-03-06 11:45:16 -0800742 bool was_running = false;
743
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800744 while (1) {
745 ATRACE_NAME("HardwareComposer::PostThread");
746
Corey Tabaka2251d822017-04-20 16:04:07 -0700747 while (post_thread_quiescent_) {
Steven Thomas050b2c82017-03-06 11:45:16 -0800748 std::unique_lock<std::mutex> lock(post_thread_mutex_);
Corey Tabaka2251d822017-04-20 16:04:07 -0700749 ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
750
751 // Tear down resources.
752 OnPostThreadPaused();
753
754 was_running = false;
755 post_thread_resumed_ = false;
756 post_thread_ready_.notify_all();
757
758 if (post_thread_state_ & PostThreadState::Quit) {
759 ALOGI("HardwareComposer::PostThread: Quitting.");
760 return;
Steven Thomas282a5ed2017-02-07 18:07:01 -0800761 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700762
763 post_thread_wait_.wait(lock, [this] { return !post_thread_quiescent_; });
764
765 post_thread_resumed_ = true;
766 post_thread_ready_.notify_all();
767
768 ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
Steven Thomas050b2c82017-03-06 11:45:16 -0800769 }
770
771 if (!was_running) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700772 // Setup resources.
Steven Thomas050b2c82017-03-06 11:45:16 -0800773 OnPostThreadResumed();
774 was_running = true;
Corey Tabaka2251d822017-04-20 16:04:07 -0700775
776 // Try to setup the scheduler policy if it failed during startup. Only
777 // attempt to do this on transitions from inactive to active to avoid
778 // spamming the system with RPCs and log messages.
779 if (!thread_policy_setup) {
780 thread_policy_setup =
781 SetThreadPolicy("graphics:high", "/system/performance");
782 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800783 }
784
785 int64_t vsync_timestamp = 0;
786 {
787 std::array<char, 128> buf;
788 snprintf(buf.data(), buf.size(), "wait_vsync|vsync=%d|",
789 vsync_count_ + 1);
790 ATRACE_NAME(buf.data());
791
Corey Tabaka2251d822017-04-20 16:04:07 -0700792 const int error = WaitForVSync(&vsync_timestamp);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800793 ALOGE_IF(
794 error < 0,
795 "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
796 strerror(-error));
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800797 // Don't bother processing this frame if a pause was requested
Steven Thomas050b2c82017-03-06 11:45:16 -0800798 if (error == kPostThreadInterrupted)
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800799 continue;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800800 }
801
802 ++vsync_count_;
803
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800804 if (pose_client_) {
805 // Signal the pose service with vsync info.
806 // Display timestamp is in the middle of scanout.
807 privateDvrPoseNotifyVsync(pose_client_, vsync_count_,
808 vsync_timestamp + photon_offset_ns,
809 ns_per_frame, right_eye_photon_offset_ns);
810 }
811
Corey Tabaka2251d822017-04-20 16:04:07 -0700812 const bool layer_config_changed = UpdateLayerConfig();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800813
814 // Signal all of the vsync clients. Because absolute time is used for the
815 // wakeup time below, this can take a little time if necessary.
816 if (vsync_callback_)
Corey Tabaka2251d822017-04-20 16:04:07 -0700817 vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp,
818 /*frame_time_estimate*/ 0, vsync_count_);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800819
820 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700821 // Sleep until shortly before vsync.
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800822 ATRACE_NAME("sleep");
823
Corey Tabaka2251d822017-04-20 16:04:07 -0700824 const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
825 const int64_t now_ns = GetSystemClockNs();
826 const int64_t sleep_time_ns =
827 display_time_est_ns - now_ns - kFramePostOffsetNs;
828 const int64_t wakeup_time_ns = display_time_est_ns - kFramePostOffsetNs;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800829
830 ATRACE_INT64("sleep_time_ns", sleep_time_ns);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800831 if (sleep_time_ns > 0) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700832 int error = SleepUntil(wakeup_time_ns);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800833 ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s",
834 strerror(-error));
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700835 if (error == kPostThreadInterrupted) {
836 if (layer_config_changed) {
837 // If the layer config changed we need to validateDisplay() even if
838 // we're going to drop the frame, to flush the Composer object's
839 // internal command buffer and apply our layer changes.
840 Validate(HWC_DISPLAY_PRIMARY);
841 }
Steven Thomas050b2c82017-03-06 11:45:16 -0800842 continue;
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700843 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800844 }
845 }
846
Corey Tabaka2251d822017-04-20 16:04:07 -0700847 PostLayers();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800848 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800849}
850
Corey Tabaka2251d822017-04-20 16:04:07 -0700851// Checks for changes in the surface stack and updates the layer config to
852// accomodate the new stack.
Steven Thomas050b2c82017-03-06 11:45:16 -0800853bool HardwareComposer::UpdateLayerConfig() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700854 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
Steven Thomas050b2c82017-03-06 11:45:16 -0800855 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700856 std::unique_lock<std::mutex> lock(post_thread_mutex_);
857 if (pending_surfaces_.empty())
Steven Thomas050b2c82017-03-06 11:45:16 -0800858 return false;
Corey Tabaka2251d822017-04-20 16:04:07 -0700859
860 surfaces = std::move(pending_surfaces_);
Steven Thomas050b2c82017-03-06 11:45:16 -0800861 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800862
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800863 ATRACE_NAME("UpdateLayerConfig_HwLayers");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800864
Corey Tabaka2251d822017-04-20 16:04:07 -0700865 display_surfaces_.clear();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800866
Corey Tabaka2251d822017-04-20 16:04:07 -0700867 Layer* target_layer;
868 size_t layer_index;
869 for (layer_index = 0;
870 layer_index < std::min(surfaces.size(), kMaxHardwareLayers);
871 layer_index++) {
872 // The bottom layer is opaque, other layers blend.
873 HWC::BlendMode blending =
874 layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
875 layers_[layer_index].Setup(surfaces[layer_index], blending,
876 display_transform_, HWC::Composition::Device,
877 layer_index);
878 display_surfaces_.push_back(surfaces[layer_index]);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800879 }
880
Corey Tabaka2251d822017-04-20 16:04:07 -0700881 // Clear unused layers.
882 for (size_t i = layer_index; i < kMaxHardwareLayers; i++)
883 layers_[i].Reset();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800884
Corey Tabaka2251d822017-04-20 16:04:07 -0700885 active_layer_count_ = layer_index;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800886 ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
887 active_layer_count_);
888
Corey Tabaka2251d822017-04-20 16:04:07 -0700889 // Any surfaces left over could not be assigned a hardware layer and will
890 // not be displayed.
891 ALOGW_IF(surfaces.size() != display_surfaces_.size(),
892 "HardwareComposer::UpdateLayerConfig: More surfaces than layers: "
893 "pending_surfaces=%zu display_surfaces=%zu",
894 surfaces.size(), display_surfaces_.size());
895
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800896 return true;
897}
898
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800899void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
900 vsync_callback_ = callback;
901}
902
903void HardwareComposer::HwcRefresh(hwc2_callback_data_t /*data*/,
904 hwc2_display_t /*display*/) {
905 // TODO(eieio): implement invalidate callbacks.
906}
907
908void HardwareComposer::HwcVSync(hwc2_callback_data_t /*data*/,
909 hwc2_display_t /*display*/,
910 int64_t /*timestamp*/) {
911 ATRACE_NAME(__PRETTY_FUNCTION__);
912 // Intentionally empty. HWC may require a callback to be set to enable vsync
913 // signals. We bypass this callback thread by monitoring the vsync event
914 // directly, but signals still need to be enabled.
915}
916
917void HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/,
918 hwc2_display_t /*display*/,
919 hwc2_connection_t /*connected*/) {
920 // TODO(eieio): implement display hotplug callbacks.
921}
922
Steven Thomas3cfac282017-02-06 12:29:30 -0800923void HardwareComposer::OnHardwareComposerRefresh() {
924 // TODO(steventhomas): Handle refresh.
925}
926
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800927void HardwareComposer::SetBacklightBrightness(int brightness) {
928 if (backlight_brightness_fd_) {
929 std::array<char, 32> text;
930 const int length = snprintf(text.data(), text.size(), "%d", brightness);
931 write(backlight_brightness_fd_.Get(), text.data(), length);
932 }
933}
934
Corey Tabaka2251d822017-04-20 16:04:07 -0700935void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
936 const HWCDisplayMetrics* metrics) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800937 hwc2_hidl_ = hwc2_hidl;
938 display_metrics_ = metrics;
939}
940
941void Layer::Reset() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800942 if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
943 hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
944 hardware_composer_layer_ = 0;
945 }
946
Corey Tabaka2251d822017-04-20 16:04:07 -0700947 z_order_ = 0;
948 blending_ = HWC::BlendMode::None;
949 transform_ = HWC::Transform::None;
950 composition_type_ = HWC::Composition::Invalid;
951 target_composition_type_ = composition_type_;
952 source_ = EmptyVariant{};
953 acquire_fence_.Close();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800954 surface_rect_functions_applied_ = false;
955}
956
Corey Tabaka2251d822017-04-20 16:04:07 -0700957void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
958 HWC::BlendMode blending, HWC::Transform transform,
959 HWC::Composition composition_type, size_t z_order) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800960 Reset();
Corey Tabaka2251d822017-04-20 16:04:07 -0700961 z_order_ = z_order;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800962 blending_ = blending;
963 transform_ = transform;
Corey Tabaka2251d822017-04-20 16:04:07 -0700964 composition_type_ = HWC::Composition::Invalid;
965 target_composition_type_ = composition_type;
966 source_ = SourceSurface{surface};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800967 CommonLayerSetup();
968}
969
970void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
Corey Tabaka2251d822017-04-20 16:04:07 -0700971 HWC::BlendMode blending, HWC::Transform transform,
972 HWC::Composition composition_type, size_t z_order) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800973 Reset();
Corey Tabaka2251d822017-04-20 16:04:07 -0700974 z_order_ = z_order;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800975 blending_ = blending;
976 transform_ = transform;
Corey Tabaka2251d822017-04-20 16:04:07 -0700977 composition_type_ = HWC::Composition::Invalid;
978 target_composition_type_ = composition_type;
979 source_ = SourceBuffer{buffer};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800980 CommonLayerSetup();
981}
982
Corey Tabaka2251d822017-04-20 16:04:07 -0700983void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
984 if (source_.is<SourceBuffer>())
985 std::get<SourceBuffer>(source_) = {buffer};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800986}
987
Corey Tabaka2251d822017-04-20 16:04:07 -0700988void Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; }
989void Layer::SetZOrder(size_t z_order) { z_order_ = z_order; }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800990
991IonBuffer* Layer::GetBuffer() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700992 struct Visitor {
993 IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
994 IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
995 IonBuffer* operator()(EmptyVariant) { return nullptr; }
996 };
997 return source_.Visit(Visitor{});
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800998}
999
1000void Layer::UpdateLayerSettings() {
1001 if (!IsLayerSetup()) {
Corey Tabaka2251d822017-04-20 16:04:07 -07001002 ALOGE(
1003 "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
1004 "unused Layer!");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001005 return;
1006 }
1007
Corey Tabaka2251d822017-04-20 16:04:07 -07001008 HWC::Error error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001009 hwc2_display_t display = HWC_DISPLAY_PRIMARY;
1010
Corey Tabaka2251d822017-04-20 16:04:07 -07001011 error = hwc2_hidl_->setLayerCompositionType(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001012 display, hardware_composer_layer_,
Corey Tabaka2251d822017-04-20 16:04:07 -07001013 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1014 ALOGE_IF(
1015 error != HWC::Error::None,
1016 "Layer::UpdateLayerSettings: Error setting layer composition type: %s",
1017 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001018
Corey Tabaka2251d822017-04-20 16:04:07 -07001019 error = hwc2_hidl_->setLayerBlendMode(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001020 display, hardware_composer_layer_,
Corey Tabaka2251d822017-04-20 16:04:07 -07001021 blending_.cast<Hwc2::IComposerClient::BlendMode>());
1022 ALOGE_IF(error != HWC::Error::None,
1023 "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
1024 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001025
Corey Tabaka2251d822017-04-20 16:04:07 -07001026 // TODO(eieio): Use surface attributes or some other mechanism to control
1027 // the layer display frame.
1028 error = hwc2_hidl_->setLayerDisplayFrame(
1029 display, hardware_composer_layer_,
1030 {0, 0, display_metrics_->width, display_metrics_->height});
1031 ALOGE_IF(error != HWC::Error::None,
1032 "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
1033 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001034
Corey Tabaka2251d822017-04-20 16:04:07 -07001035 error = hwc2_hidl_->setLayerVisibleRegion(
1036 display, hardware_composer_layer_,
1037 {{0, 0, display_metrics_->width, display_metrics_->height}});
1038 ALOGE_IF(error != HWC::Error::None,
1039 "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
1040 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001041
Corey Tabaka2251d822017-04-20 16:04:07 -07001042 error =
1043 hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
1044 ALOGE_IF(error != HWC::Error::None,
1045 "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
1046 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001047
Corey Tabaka2251d822017-04-20 16:04:07 -07001048 error =
1049 hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
1050 ALOGE_IF(error != HWC::Error::None,
1051 "Layer::UpdateLayerSettings: Error setting z_ order: %s",
1052 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001053}
1054
1055void Layer::CommonLayerSetup() {
Corey Tabaka2251d822017-04-20 16:04:07 -07001056 HWC::Error error =
1057 hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
1058 ALOGE_IF(
1059 error != HWC::Error::None,
1060 "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
1061 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001062 UpdateLayerSettings();
1063}
1064
1065void Layer::Prepare() {
1066 int right, bottom;
Daniel Nicoara1f42e3a2017-04-10 13:27:32 -04001067 sp<GraphicBuffer> handle;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001068
Corey Tabaka2251d822017-04-20 16:04:07 -07001069 // Acquire the next buffer according to the type of source.
1070 IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
1071 std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
1072 });
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001073
Corey Tabaka2251d822017-04-20 16:04:07 -07001074 // When a layer is first setup there may be some time before the first buffer
1075 // arrives. Setup the HWC layer as a solid color to stall for time until the
1076 // first buffer arrives. Once the first buffer arrives there will always be a
1077 // buffer for the frame even if it is old.
1078 if (!handle.get()) {
1079 if (composition_type_ == HWC::Composition::Invalid) {
1080 composition_type_ = HWC::Composition::SolidColor;
1081 hwc2_hidl_->setLayerCompositionType(
1082 HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1083 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1084 Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
1085 hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1086 layer_color);
1087 } else {
1088 // The composition type is already set. Nothing else to do until a
1089 // buffer arrives.
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001090 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001091 } else {
Corey Tabaka2251d822017-04-20 16:04:07 -07001092 if (composition_type_ != target_composition_type_) {
1093 composition_type_ = target_composition_type_;
1094 hwc2_hidl_->setLayerCompositionType(
1095 HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
1096 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1097 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001098
Corey Tabaka2251d822017-04-20 16:04:07 -07001099 HWC::Error error{HWC::Error::None};
1100 error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
1101 hardware_composer_layer_, 0, handle,
1102 acquire_fence_.Get());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001103
Corey Tabaka2251d822017-04-20 16:04:07 -07001104 ALOGE_IF(error != HWC::Error::None,
1105 "Layer::Prepare: Error setting layer buffer: %s",
1106 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001107
Corey Tabaka2251d822017-04-20 16:04:07 -07001108 if (!surface_rect_functions_applied_) {
1109 const float float_right = right;
1110 const float float_bottom = bottom;
1111 error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
1112 hardware_composer_layer_,
1113 {0, 0, float_right, float_bottom});
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001114
Corey Tabaka2251d822017-04-20 16:04:07 -07001115 ALOGE_IF(error != HWC::Error::None,
1116 "Layer::Prepare: Error setting layer source crop: %s",
1117 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001118
Corey Tabaka2251d822017-04-20 16:04:07 -07001119 surface_rect_functions_applied_ = true;
1120 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001121 }
1122}
1123
1124void Layer::Finish(int release_fence_fd) {
Corey Tabaka2251d822017-04-20 16:04:07 -07001125 IfAnyOf<SourceSurface, SourceBuffer>::Call(
1126 &source_, [release_fence_fd](auto& source) {
1127 source.Finish(LocalHandle(release_fence_fd));
1128 });
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001129}
1130
Corey Tabaka2251d822017-04-20 16:04:07 -07001131void Layer::Drop() { acquire_fence_.Close(); }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001132
1133} // namespace dvr
1134} // namespace android