blob: 44ce78c854b6578145fbe20ecdcb8b28509ef90c [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>
Corey Tabakab3732f02017-09-16 00:58:54 -07008#include <stdint.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08009#include <sync/sync.h>
10#include <sys/eventfd.h>
11#include <sys/prctl.h>
12#include <sys/resource.h>
13#include <sys/system_properties.h>
14#include <sys/timerfd.h>
Corey Tabakab3732f02017-09-16 00:58:54 -070015#include <sys/types.h>
Corey Tabaka2251d822017-04-20 16:04:07 -070016#include <time.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080017#include <unistd.h>
18#include <utils/Trace.h>
19
20#include <algorithm>
Corey Tabaka2251d822017-04-20 16:04:07 -070021#include <chrono>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080022#include <functional>
23#include <map>
Corey Tabaka0b485c92017-05-19 12:02:58 -070024#include <sstream>
25#include <string>
John Bates954796e2017-05-11 11:00:31 -070026#include <tuple>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080027
Corey Tabaka2251d822017-04-20 16:04:07 -070028#include <dvr/dvr_display_types.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080029#include <dvr/performance_client_api.h>
30#include <private/dvr/clock_ns.h>
Corey Tabaka2251d822017-04-20 16:04:07 -070031#include <private/dvr/ion_buffer.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080032
Steven Thomasb02664d2017-07-26 18:48:28 -070033using android::hardware::Return;
34using android::hardware::Void;
Corey Tabakab3732f02017-09-16 00:58:54 -070035using android::pdx::ErrorStatus;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080036using android::pdx::LocalHandle;
Corey Tabakab3732f02017-09-16 00:58:54 -070037using android::pdx::Status;
Corey Tabaka2251d822017-04-20 16:04:07 -070038using android::pdx::rpc::EmptyVariant;
39using android::pdx::rpc::IfAnyOf;
40
41using namespace std::chrono_literals;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080042
43namespace android {
44namespace dvr {
45
46namespace {
47
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080048const char kDvrPerformanceProperty[] = "sys.dvr.performance";
Corey Tabaka451256f2017-08-22 11:59:15 -070049const char kDvrStandaloneProperty[] = "ro.boot.vr";
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080050
Luke Song4b788322017-03-24 14:17:31 -070051const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080052
Steven Thomasbfe46a02018-02-16 14:27:35 -080053const char kUseExternalDisplayProperty[] = "persist.vr.use_external_display";
54
Steven Thomasaf336272018-01-04 17:36:47 -080055// How long to wait after boot finishes before we turn the display off.
56constexpr int kBootFinishedDisplayOffTimeoutSec = 10;
57
Steven Thomasbfe46a02018-02-16 14:27:35 -080058constexpr int kDefaultDisplayWidth = 1920;
59constexpr int kDefaultDisplayHeight = 1080;
60constexpr int64_t kDefaultVsyncPeriodNs = 16666667;
61// Hardware composer reports dpi as dots per thousand inches (dpi * 1000).
62constexpr int kDefaultDpi = 400000;
63
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
Corey Tabakab3732f02017-09-16 00:58:54 -070097// Utility to generate scoped tracers with arguments.
98// TODO(eieio): Move/merge this into utils/Trace.h?
99class TraceArgs {
100 public:
101 template <typename... Args>
102 TraceArgs(const char* format, Args&&... args) {
103 std::array<char, 1024> buffer;
104 snprintf(buffer.data(), buffer.size(), format, std::forward<Args>(args)...);
105 atrace_begin(ATRACE_TAG, buffer.data());
106 }
107
108 ~TraceArgs() { atrace_end(ATRACE_TAG); }
109
110 private:
111 TraceArgs(const TraceArgs&) = delete;
112 void operator=(const TraceArgs&) = delete;
113};
114
115// Macro to define a scoped tracer with arguments. Uses PASTE(x, y) macro
116// defined in utils/Trace.h.
117#define TRACE_FORMAT(format, ...) \
118 TraceArgs PASTE(__tracer, __LINE__) { format, ##__VA_ARGS__ }
119
Steven Thomasbfe46a02018-02-16 14:27:35 -0800120// Returns "primary" or "external". Useful for writing more readable logs.
121const char* GetDisplayName(bool is_primary) {
122 return is_primary ? "primary" : "external";
123}
124
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800125} // anonymous namespace
126
Corey Tabaka2251d822017-04-20 16:04:07 -0700127HardwareComposer::HardwareComposer()
Steven Thomasb02664d2017-07-26 18:48:28 -0700128 : initialized_(false), request_display_callback_(nullptr) {}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800129
130HardwareComposer::~HardwareComposer(void) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700131 UpdatePostThreadState(PostThreadState::Quit, true);
132 if (post_thread_.joinable())
Steven Thomas050b2c82017-03-06 11:45:16 -0800133 post_thread_.join();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800134}
135
Steven Thomasb02664d2017-07-26 18:48:28 -0700136bool HardwareComposer::Initialize(
Steven Thomas6e8f7062017-11-22 14:15:29 -0800137 Hwc2::Composer* composer, hwc2_display_t primary_display_id,
138 RequestDisplayCallback request_display_callback) {
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800139 if (initialized_) {
140 ALOGE("HardwareComposer::Initialize: already initialized.");
141 return false;
142 }
143
Corey Tabaka451256f2017-08-22 11:59:15 -0700144 is_standalone_device_ = property_get_bool(kDvrStandaloneProperty, false);
145
Steven Thomasb02664d2017-07-26 18:48:28 -0700146 request_display_callback_ = request_display_callback;
147
Steven Thomasbfe46a02018-02-16 14:27:35 -0800148 primary_display_ = GetDisplayParams(composer, primary_display_id, true);
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700149
Corey Tabaka2251d822017-04-20 16:04:07 -0700150 post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
Steven Thomas050b2c82017-03-06 11:45:16 -0800151 LOG_ALWAYS_FATAL_IF(
Corey Tabaka2251d822017-04-20 16:04:07 -0700152 !post_thread_event_fd_,
Steven Thomas050b2c82017-03-06 11:45:16 -0800153 "HardwareComposer: Failed to create interrupt event fd : %s",
154 strerror(errno));
155
156 post_thread_ = std::thread(&HardwareComposer::PostThread, this);
157
Stephen Kiazyk016e5e32017-02-21 17:09:22 -0800158 initialized_ = true;
159
160 return initialized_;
161}
162
Steven Thomas050b2c82017-03-06 11:45:16 -0800163void HardwareComposer::Enable() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700164 UpdatePostThreadState(PostThreadState::Suspended, false);
Steven Thomas050b2c82017-03-06 11:45:16 -0800165}
166
167void HardwareComposer::Disable() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700168 UpdatePostThreadState(PostThreadState::Suspended, true);
Steven Thomas7f8761e2018-01-18 18:49:59 -0800169
170 std::unique_lock<std::mutex> lock(post_thread_mutex_);
171 post_thread_ready_.wait(lock, [this] {
172 return !post_thread_resumed_;
173 });
Steven Thomas050b2c82017-03-06 11:45:16 -0800174}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800175
Steven Thomasaf336272018-01-04 17:36:47 -0800176void HardwareComposer::OnBootFinished() {
177 std::lock_guard<std::mutex> lock(post_thread_mutex_);
178 if (boot_finished_)
179 return;
180 boot_finished_ = true;
181 post_thread_wait_.notify_one();
182 if (is_standalone_device_)
183 request_display_callback_(true);
184}
185
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 }
Steven Thomas050b2c82017-03-06 11:45:16 -0800215}
Steven Thomas282a5ed2017-02-07 18:07:01 -0800216
Steven Thomasbfe46a02018-02-16 14:27:35 -0800217void HardwareComposer::CreateComposer() {
218 if (composer_)
219 return;
220 composer_.reset(new Hwc2::impl::Composer("default"));
221 composer_callback_ = new ComposerCallback;
222 composer_->registerCallback(composer_callback_);
223 LOG_ALWAYS_FATAL_IF(!composer_callback_->GotFirstHotplug(),
224 "Registered composer callback but didn't get hotplug for primary"
225 " display");
226}
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700227
Steven Thomasbfe46a02018-02-16 14:27:35 -0800228void HardwareComposer::OnPostThreadResumed() {
229 ALOGI("OnPostThreadResumed");
230 EnableDisplay(*target_display_, true);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800231
Steven Thomas050b2c82017-03-06 11:45:16 -0800232 // Trigger target-specific performance mode change.
233 property_set(kDvrPerformanceProperty, "performance");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800234}
235
Steven Thomas050b2c82017-03-06 11:45:16 -0800236void HardwareComposer::OnPostThreadPaused() {
Steven Thomasbfe46a02018-02-16 14:27:35 -0800237 ALOGI("OnPostThreadPaused");
Corey Tabaka2251d822017-04-20 16:04:07 -0700238 retire_fence_fds_.clear();
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700239 layers_.clear();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800240
Steven Thomasbfe46a02018-02-16 14:27:35 -0800241 // Phones create a new composer client on resume and destroy it on pause.
242 // Standalones only create the composer client once and then use SetPowerMode
243 // to control the screen on pause/resume.
Corey Tabaka451256f2017-08-22 11:59:15 -0700244 if (!is_standalone_device_) {
245 composer_callback_ = nullptr;
246 composer_.reset(nullptr);
Corey Tabaka451256f2017-08-22 11:59:15 -0700247 } else {
Steven Thomasbfe46a02018-02-16 14:27:35 -0800248 EnableDisplay(*target_display_, false);
Corey Tabaka451256f2017-08-22 11:59:15 -0700249 }
Steven Thomas0af4b9f2017-04-26 14:34:01 -0700250
Steven Thomas050b2c82017-03-06 11:45:16 -0800251 // Trigger target-specific performance mode change.
252 property_set(kDvrPerformanceProperty, "idle");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800253}
254
Steven Thomasaf336272018-01-04 17:36:47 -0800255bool HardwareComposer::PostThreadCondWait(std::unique_lock<std::mutex>& lock,
256 int timeout_sec,
257 const std::function<bool()>& pred) {
258 auto pred_with_quit = [&] {
259 return pred() || (post_thread_state_ & PostThreadState::Quit);
260 };
261 if (timeout_sec >= 0) {
262 post_thread_wait_.wait_for(lock, std::chrono::seconds(timeout_sec),
263 pred_with_quit);
264 } else {
265 post_thread_wait_.wait(lock, pred_with_quit);
266 }
267 if (post_thread_state_ & PostThreadState::Quit) {
268 ALOGI("HardwareComposer::PostThread: Quitting.");
269 return true;
270 }
271 return false;
272}
273
Corey Tabaka2251d822017-04-20 16:04:07 -0700274HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800275 uint32_t num_types;
276 uint32_t num_requests;
Corey Tabaka2251d822017-04-20 16:04:07 -0700277 HWC::Error error =
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700278 composer_->validateDisplay(display, &num_types, &num_requests);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800279
280 if (error == HWC2_ERROR_HAS_CHANGES) {
Steven Thomasbfe46a02018-02-16 14:27:35 -0800281 ALOGE("Hardware composer has requested composition changes, "
282 "which we don't support.");
283 // Accept the changes anyway and see if we can get something on the screen.
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700284 error = composer_->acceptDisplayChanges(display);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800285 }
286
287 return error;
288}
289
Steven Thomasbfe46a02018-02-16 14:27:35 -0800290bool HardwareComposer::EnableVsync(const DisplayParams& display, bool enabled) {
291 HWC::Error error = composer_->setVsyncEnabled(display.id,
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800292 (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
293 : HWC2_VSYNC_DISABLE));
Steven Thomasbfe46a02018-02-16 14:27:35 -0800294 if (error != HWC::Error::None) {
295 ALOGE("Error attempting to %s vsync on %s display: %s",
296 enabled ? "enable" : "disable", GetDisplayName(display.is_primary),
297 error.to_string().c_str());
298 }
299 return error == HWC::Error::None;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800300}
301
Steven Thomasbfe46a02018-02-16 14:27:35 -0800302bool HardwareComposer::SetPowerMode(const DisplayParams& display, bool active) {
303 ALOGI("Turning %s display %s", GetDisplayName(display.is_primary),
304 active ? "on" : "off");
Corey Tabaka451256f2017-08-22 11:59:15 -0700305 HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off;
Steven Thomasbfe46a02018-02-16 14:27:35 -0800306 HWC::Error error = composer_->setPowerMode(display.id,
Steven Thomas6e8f7062017-11-22 14:15:29 -0800307 power_mode.cast<Hwc2::IComposerClient::PowerMode>());
Steven Thomasbfe46a02018-02-16 14:27:35 -0800308 if (error != HWC::Error::None) {
309 ALOGE("Error attempting to turn %s display %s: %s",
310 GetDisplayName(display.is_primary), active ? "on" : "off",
311 error.to_string().c_str());
312 }
313 return error == HWC::Error::None;
314}
315
316bool HardwareComposer::EnableDisplay(const DisplayParams& display,
317 bool enabled) {
318 bool power_result;
319 bool vsync_result;
320 // When turning a display on, we set the power state then set vsync. When
321 // turning a display off we do it in the opposite order.
322 if (enabled) {
323 power_result = SetPowerMode(display, enabled);
324 vsync_result = EnableVsync(display, enabled);
325 } else {
326 vsync_result = EnableVsync(display, enabled);
327 power_result = SetPowerMode(display, enabled);
328 }
329 return power_result && vsync_result;
Corey Tabaka451256f2017-08-22 11:59:15 -0700330}
331
Corey Tabaka2251d822017-04-20 16:04:07 -0700332HWC::Error HardwareComposer::Present(hwc2_display_t display) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800333 int32_t present_fence;
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700334 HWC::Error error = composer_->presentDisplay(display, &present_fence);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800335
336 // According to the documentation, this fence is signaled at the time of
337 // vsync/DMA for physical displays.
Corey Tabaka2251d822017-04-20 16:04:07 -0700338 if (error == HWC::Error::None) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800339 ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
340 retire_fence_fds_.emplace_back(present_fence);
341 } else {
342 ATRACE_INT("HardwareComposer: PresentResult", error);
343 }
344
345 return error;
346}
347
Steven Thomasbfe46a02018-02-16 14:27:35 -0800348DisplayParams HardwareComposer::GetDisplayParams(
349 Hwc2::Composer* composer, hwc2_display_t display, bool is_primary) {
350 DisplayParams params;
351 params.id = display;
352 params.is_primary = is_primary;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800353
Steven Thomasbfe46a02018-02-16 14:27:35 -0800354 Hwc2::Config config;
355 HWC::Error error = composer->getActiveConfig(display, &config);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800356
Steven Thomasbfe46a02018-02-16 14:27:35 -0800357 if (error == HWC::Error::None) {
358 auto get_attr = [&](hwc2_attribute_t attr, const char* attr_name)
359 -> std::optional<int32_t> {
360 int32_t val;
361 HWC::Error error = composer->getDisplayAttribute(
362 display, config, (Hwc2::IComposerClient::Attribute)attr, &val);
363 if (error != HWC::Error::None) {
364 ALOGE("Failed to get %s display attr %s: %s",
365 GetDisplayName(is_primary), attr_name,
366 error.to_string().c_str());
367 return std::nullopt;
368 }
369 return val;
370 };
371
372 auto width = get_attr(HWC2_ATTRIBUTE_WIDTH, "width");
373 auto height = get_attr(HWC2_ATTRIBUTE_HEIGHT, "height");
374
375 if (width && height) {
376 params.width = *width;
377 params.height = *height;
378 } else {
379 ALOGI("Failed to get width and/or height for %s display. Using default"
380 " size %dx%d.", GetDisplayName(is_primary), kDefaultDisplayWidth,
381 kDefaultDisplayHeight);
382 params.width = kDefaultDisplayWidth;
383 params.height = kDefaultDisplayHeight;
384 }
385
386 auto vsync_period = get_attr(HWC2_ATTRIBUTE_VSYNC_PERIOD, "vsync period");
387 if (vsync_period) {
388 params.vsync_period_ns = *vsync_period;
389 } else {
390 ALOGI("Failed to get vsync period for %s display. Using default vsync"
391 " period %.2fms", GetDisplayName(is_primary),
392 static_cast<float>(kDefaultVsyncPeriodNs) / 1000000);
393 params.vsync_period_ns = kDefaultVsyncPeriodNs;
394 }
395
396 auto dpi_x = get_attr(HWC2_ATTRIBUTE_DPI_X, "DPI X");
397 auto dpi_y = get_attr(HWC2_ATTRIBUTE_DPI_Y, "DPI Y");
398 if (dpi_x && dpi_y) {
399 params.dpi.x = *dpi_x;
400 params.dpi.y = *dpi_y;
401 } else {
402 ALOGI("Failed to get dpi_x and/or dpi_y for %s display. Using default"
403 " dpi %d.", GetDisplayName(is_primary), kDefaultDpi);
404 params.dpi.x = kDefaultDpi;
405 params.dpi.y = kDefaultDpi;
406 }
407 } else {
408 ALOGE("HardwareComposer: Failed to get current %s display config: %d."
409 " Using default display values.",
410 GetDisplayName(is_primary), error.value);
411 params.width = kDefaultDisplayWidth;
412 params.height = kDefaultDisplayHeight;
413 params.dpi.x = kDefaultDpi;
414 params.dpi.y = kDefaultDpi;
415 params.vsync_period_ns = kDefaultVsyncPeriodNs;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800416 }
417
Steven Thomasbfe46a02018-02-16 14:27:35 -0800418 ALOGI(
419 "HardwareComposer: %s display attributes: width=%d height=%d "
420 "vsync_period_ns=%d DPI=%dx%d",
421 GetDisplayName(is_primary),
422 params.width,
423 params.height,
424 params.vsync_period_ns,
425 params.dpi.x,
426 params.dpi.y);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800427
Steven Thomasbfe46a02018-02-16 14:27:35 -0800428 return params;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800429}
430
Corey Tabaka0b485c92017-05-19 12:02:58 -0700431std::string HardwareComposer::Dump() {
432 std::unique_lock<std::mutex> lock(post_thread_mutex_);
433 std::ostringstream stream;
434
Steven Thomasbfe46a02018-02-16 14:27:35 -0800435 auto print_display_metrics = [&](const DisplayParams& params) {
436 stream << GetDisplayName(params.is_primary)
437 << " display metrics: " << params.width << "x"
438 << params.height << " " << (params.dpi.x / 1000.0)
439 << "x" << (params.dpi.y / 1000.0) << " dpi @ "
440 << (1000000000.0 / params.vsync_period_ns) << " Hz"
441 << std::endl;
442 };
443
444 print_display_metrics(primary_display_);
445 if (external_display_)
446 print_display_metrics(*external_display_);
Corey Tabaka0b485c92017-05-19 12:02:58 -0700447
448 stream << "Post thread resumed: " << post_thread_resumed_ << std::endl;
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700449 stream << "Active layers: " << layers_.size() << std::endl;
Corey Tabaka0b485c92017-05-19 12:02:58 -0700450 stream << std::endl;
451
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700452 for (size_t i = 0; i < layers_.size(); i++) {
Corey Tabaka0b485c92017-05-19 12:02:58 -0700453 stream << "Layer " << i << ":";
454 stream << " type=" << layers_[i].GetCompositionType().to_string();
455 stream << " surface_id=" << layers_[i].GetSurfaceId();
456 stream << " buffer_id=" << layers_[i].GetBufferId();
457 stream << std::endl;
458 }
459 stream << std::endl;
460
461 if (post_thread_resumed_) {
462 stream << "Hardware Composer Debug Info:" << std::endl;
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700463 stream << composer_->dumpDebugInfo();
Corey Tabaka0b485c92017-05-19 12:02:58 -0700464 }
465
466 return stream.str();
467}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800468
Steven Thomasbfe46a02018-02-16 14:27:35 -0800469void HardwareComposer::PostLayers(hwc2_display_t display) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800470 ATRACE_NAME("HardwareComposer::PostLayers");
471
472 // Setup the hardware composer layers with current buffers.
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700473 for (auto& layer : layers_) {
474 layer.Prepare();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800475 }
476
477 // Now that we have taken in a frame from the application, we have a chance
478 // to drop the frame before passing the frame along to HWC.
479 // If the display driver has become backed up, we detect it here and then
480 // react by skipping this frame to catch up latency.
481 while (!retire_fence_fds_.empty() &&
482 (!retire_fence_fds_.front() ||
483 sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) {
484 // There are only 2 fences in here, no performance problem to shift the
485 // array of ints.
486 retire_fence_fds_.erase(retire_fence_fds_.begin());
487 }
488
George Burgess IV353a6f62017-06-26 17:13:09 -0700489 const bool is_fence_pending = static_cast<int32_t>(retire_fence_fds_.size()) >
John Bates954796e2017-05-11 11:00:31 -0700490 post_thread_config_.allowed_pending_fence_count;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800491
Corey Tabakab3732f02017-09-16 00:58:54 -0700492 if (is_fence_pending) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800493 ATRACE_INT("frame_skip_count", ++frame_skip_count_);
494
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800495 ALOGW_IF(is_fence_pending,
496 "Warning: dropping a frame to catch up with HWC (pending = %zd)",
497 retire_fence_fds_.size());
498
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700499 for (auto& layer : layers_) {
500 layer.Drop();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800501 }
502 return;
503 } else {
504 // Make the transition more obvious in systrace when the frame skip happens
505 // above.
506 ATRACE_INT("frame_skip_count", 0);
507 }
508
Corey Tabaka89bbefc2017-06-06 16:14:21 -0700509#if TRACE > 1
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700510 for (size_t i = 0; i < layers_.size(); i++) {
Corey Tabaka0b485c92017-05-19 12:02:58 -0700511 ALOGI("HardwareComposer::PostLayers: layer=%zu buffer_id=%d composition=%s",
512 i, layers_[i].GetBufferId(),
Corey Tabaka2251d822017-04-20 16:04:07 -0700513 layers_[i].GetCompositionType().to_string().c_str());
Corey Tabaka0b485c92017-05-19 12:02:58 -0700514 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800515#endif
516
Steven Thomasbfe46a02018-02-16 14:27:35 -0800517 HWC::Error error = Validate(display);
John Bates46684842017-12-13 15:26:50 -0800518 if (error != HWC::Error::None) {
Steven Thomasbfe46a02018-02-16 14:27:35 -0800519 ALOGE("HardwareComposer::PostLayers: Validate failed: %s display=%" PRIu64,
520 error.to_string().c_str(), display);
John Bates46684842017-12-13 15:26:50 -0800521 return;
522 }
523
Steven Thomasbfe46a02018-02-16 14:27:35 -0800524 error = Present(display);
Corey Tabaka2251d822017-04-20 16:04:07 -0700525 if (error != HWC::Error::None) {
526 ALOGE("HardwareComposer::PostLayers: Present failed: %s",
527 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800528 return;
529 }
530
531 std::vector<Hwc2::Layer> out_layers;
532 std::vector<int> out_fences;
Steven Thomasbfe46a02018-02-16 14:27:35 -0800533 error = composer_->getReleaseFences(display,
Steven Thomas6e8f7062017-11-22 14:15:29 -0800534 &out_layers, &out_fences);
Corey Tabaka2251d822017-04-20 16:04:07 -0700535 ALOGE_IF(error != HWC::Error::None,
536 "HardwareComposer::PostLayers: Failed to get release fences: %s",
537 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800538
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700539 // Perform post-frame bookkeeping.
Corey Tabaka2251d822017-04-20 16:04:07 -0700540 uint32_t num_elements = out_layers.size();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800541 for (size_t i = 0; i < num_elements; ++i) {
Corey Tabaka2c4aea32017-08-31 20:01:15 -0700542 for (auto& layer : layers_) {
543 if (layer.GetLayerHandle() == out_layers[i]) {
544 layer.Finish(out_fences[i]);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800545 }
546 }
547 }
548}
549
Steven Thomas050b2c82017-03-06 11:45:16 -0800550void HardwareComposer::SetDisplaySurfaces(
Corey Tabaka2251d822017-04-20 16:04:07 -0700551 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
Jin Qian7480c062017-03-21 00:04:15 +0000552 ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
553 surfaces.size());
Corey Tabaka2251d822017-04-20 16:04:07 -0700554 const bool display_idle = surfaces.size() == 0;
555 {
556 std::unique_lock<std::mutex> lock(post_thread_mutex_);
Steven Thomasbfe46a02018-02-16 14:27:35 -0800557 surfaces_ = std::move(surfaces);
558 surfaces_changed_ = true;
Corey Tabaka2251d822017-04-20 16:04:07 -0700559 }
560
Steven Thomasaf336272018-01-04 17:36:47 -0800561 if (request_display_callback_ && !is_standalone_device_)
Steven Thomas2ddf5672017-06-15 11:38:40 -0700562 request_display_callback_(!display_idle);
563
Corey Tabaka2251d822017-04-20 16:04:07 -0700564 // Set idle state based on whether there are any surfaces to handle.
565 UpdatePostThreadState(PostThreadState::Idle, display_idle);
Steven Thomas050b2c82017-03-06 11:45:16 -0800566}
Jin Qian7480c062017-03-21 00:04:15 +0000567
John Bates954796e2017-05-11 11:00:31 -0700568int HardwareComposer::OnNewGlobalBuffer(DvrGlobalBufferKey key,
569 IonBuffer& ion_buffer) {
Okan Arikan822b7102017-05-08 13:31:34 -0700570 if (key == DvrGlobalBuffers::kVsyncBuffer) {
571 vsync_ring_ = std::make_unique<CPUMappedBroadcastRing<DvrVsyncRing>>(
572 &ion_buffer, CPUUsageMode::WRITE_OFTEN);
573
574 if (vsync_ring_->IsMapped() == false) {
575 return -EPERM;
576 }
577 }
578
579 if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
John Bates954796e2017-05-11 11:00:31 -0700580 return MapConfigBuffer(ion_buffer);
581 }
582
583 return 0;
584}
585
586void HardwareComposer::OnDeletedGlobalBuffer(DvrGlobalBufferKey key) {
Okan Arikan822b7102017-05-08 13:31:34 -0700587 if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
John Bates954796e2017-05-11 11:00:31 -0700588 ConfigBufferDeleted();
589 }
590}
591
592int HardwareComposer::MapConfigBuffer(IonBuffer& ion_buffer) {
593 std::lock_guard<std::mutex> lock(shared_config_mutex_);
Okan Arikan6f468c62017-05-31 14:48:30 -0700594 shared_config_ring_ = DvrConfigRing();
John Bates954796e2017-05-11 11:00:31 -0700595
Okan Arikan6f468c62017-05-31 14:48:30 -0700596 if (ion_buffer.width() < DvrConfigRing::MemorySize()) {
John Bates954796e2017-05-11 11:00:31 -0700597 ALOGE("HardwareComposer::MapConfigBuffer: invalid buffer size.");
598 return -EINVAL;
599 }
600
601 void* buffer_base = 0;
602 int result = ion_buffer.Lock(ion_buffer.usage(), 0, 0, ion_buffer.width(),
603 ion_buffer.height(), &buffer_base);
604 if (result != 0) {
Corey Tabaka0b485c92017-05-19 12:02:58 -0700605 ALOGE(
606 "HardwareComposer::MapConfigBuffer: Failed to map vrflinger config "
607 "buffer.");
John Bates954796e2017-05-11 11:00:31 -0700608 return -EPERM;
609 }
610
Okan Arikan6f468c62017-05-31 14:48:30 -0700611 shared_config_ring_ = DvrConfigRing::Create(buffer_base, ion_buffer.width());
John Bates954796e2017-05-11 11:00:31 -0700612 ion_buffer.Unlock();
613
614 return 0;
615}
616
617void HardwareComposer::ConfigBufferDeleted() {
618 std::lock_guard<std::mutex> lock(shared_config_mutex_);
Okan Arikan6f468c62017-05-31 14:48:30 -0700619 shared_config_ring_ = DvrConfigRing();
John Bates954796e2017-05-11 11:00:31 -0700620}
621
622void HardwareComposer::UpdateConfigBuffer() {
623 std::lock_guard<std::mutex> lock(shared_config_mutex_);
624 if (!shared_config_ring_.is_valid())
625 return;
626 // Copy from latest record in shared_config_ring_ to local copy.
Okan Arikan6f468c62017-05-31 14:48:30 -0700627 DvrConfig record;
John Bates954796e2017-05-11 11:00:31 -0700628 if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
John Batescc65c3c2017-09-28 14:43:19 -0700629 ALOGI("DvrConfig updated: sequence %u, post offset %d",
630 shared_config_ring_sequence_, record.frame_post_offset_ns);
631 ++shared_config_ring_sequence_;
John Bates954796e2017-05-11 11:00:31 -0700632 post_thread_config_ = record;
633 }
634}
635
Corey Tabaka2251d822017-04-20 16:04:07 -0700636int HardwareComposer::PostThreadPollInterruptible(
Steven Thomasb02664d2017-07-26 18:48:28 -0700637 const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) {
Steven Thomas050b2c82017-03-06 11:45:16 -0800638 pollfd pfd[2] = {
639 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700640 .fd = event_fd.Get(),
Steven Thomas66747c12017-03-22 18:45:31 -0700641 .events = static_cast<short>(requested_events),
642 .revents = 0,
Steven Thomas050b2c82017-03-06 11:45:16 -0800643 },
644 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700645 .fd = post_thread_event_fd_.Get(),
Steven Thomas050b2c82017-03-06 11:45:16 -0800646 .events = POLLPRI | POLLIN,
647 .revents = 0,
648 },
649 };
650 int ret, error;
651 do {
Steven Thomasb02664d2017-07-26 18:48:28 -0700652 ret = poll(pfd, 2, timeout_ms);
Steven Thomas050b2c82017-03-06 11:45:16 -0800653 error = errno;
654 ALOGW_IF(ret < 0,
655 "HardwareComposer::PostThreadPollInterruptible: Error during "
656 "poll(): %s (%d)",
657 strerror(error), error);
658 } while (ret < 0 && error == EINTR);
659
660 if (ret < 0) {
661 return -error;
Steven Thomasb02664d2017-07-26 18:48:28 -0700662 } else if (ret == 0) {
663 return -ETIMEDOUT;
Steven Thomas050b2c82017-03-06 11:45:16 -0800664 } else if (pfd[0].revents != 0) {
665 return 0;
666 } else if (pfd[1].revents != 0) {
Corey Tabaka0d07cdd2017-09-28 11:15:50 -0700667 ALOGI("VrHwcPost thread interrupted: revents=%x", pfd[1].revents);
Steven Thomas050b2c82017-03-06 11:45:16 -0800668 return kPostThreadInterrupted;
669 } else {
670 return 0;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800671 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800672}
673
Steven Thomasbfe46a02018-02-16 14:27:35 -0800674// Sleep until the next predicted vsync, returning the predicted vsync
675// timestamp.
676Status<int64_t> HardwareComposer::WaitForPredictedVSync() {
677 const int64_t predicted_vsync_time = last_vsync_timestamp_ +
678 (target_display_->vsync_period_ns * vsync_prediction_interval_);
Corey Tabakab3732f02017-09-16 00:58:54 -0700679 const int error = SleepUntil(predicted_vsync_time);
680 if (error < 0) {
681 ALOGE("HardwareComposer::WaifForVSync:: Failed to sleep: %s",
682 strerror(-error));
Steven Thomasb02664d2017-07-26 18:48:28 -0700683 return error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800684 }
Corey Tabakab3732f02017-09-16 00:58:54 -0700685 return {predicted_vsync_time};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800686}
687
688int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
689 const int timer_fd = vsync_sleep_timer_fd_.Get();
690 const itimerspec wakeup_itimerspec = {
691 .it_interval = {.tv_sec = 0, .tv_nsec = 0},
692 .it_value = NsToTimespec(wakeup_timestamp),
693 };
694 int ret =
695 timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr);
696 int error = errno;
697 if (ret < 0) {
698 ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s",
699 strerror(error));
700 return -error;
701 }
702
Corey Tabaka451256f2017-08-22 11:59:15 -0700703 return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN,
704 /*timeout_ms*/ -1);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800705}
706
707void HardwareComposer::PostThread() {
708 // NOLINTNEXTLINE(runtime/int)
Steven Thomas050b2c82017-03-06 11:45:16 -0800709 prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800710
Corey Tabaka2251d822017-04-20 16:04:07 -0700711 // Set the scheduler to SCHED_FIFO with high priority. If this fails here
712 // there may have been a startup timing issue between this thread and
713 // performanced. Try again later when this thread becomes active.
714 bool thread_policy_setup =
715 SetThreadPolicy("graphics:high", "/system/performance");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800716
Steven Thomas050b2c82017-03-06 11:45:16 -0800717 // Create a timerfd based on CLOCK_MONOTINIC.
718 vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
719 LOG_ALWAYS_FATAL_IF(
720 !vsync_sleep_timer_fd_,
721 "HardwareComposer: Failed to create vsync sleep timerfd: %s",
722 strerror(errno));
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800723
Steven Thomasbfe46a02018-02-16 14:27:35 -0800724 struct VsyncEyeOffsets { int64_t left_ns, right_ns; };
Steven Thomas050b2c82017-03-06 11:45:16 -0800725 bool was_running = false;
726
Steven Thomasbfe46a02018-02-16 14:27:35 -0800727 auto get_vsync_eye_offsets = [this]() -> VsyncEyeOffsets {
728 VsyncEyeOffsets offsets;
729 offsets.left_ns =
730 GetPosePredictionTimeOffset(target_display_->vsync_period_ns);
731
732 // TODO(jbates) Query vblank time from device, when such an API is
733 // available. This value (6.3%) was measured on A00 in low persistence mode.
734 int64_t vblank_ns = target_display_->vsync_period_ns * 63 / 1000;
735 offsets.right_ns = (target_display_->vsync_period_ns - vblank_ns) / 2;
736
737 // Check property for overriding right eye offset value.
738 offsets.right_ns =
739 property_get_int64(kRightEyeOffsetProperty, offsets.right_ns);
740
741 return offsets;
742 };
743
744 VsyncEyeOffsets vsync_eye_offsets = get_vsync_eye_offsets();
745
Steven Thomasaf336272018-01-04 17:36:47 -0800746 if (is_standalone_device_) {
747 // First, wait until boot finishes.
748 std::unique_lock<std::mutex> lock(post_thread_mutex_);
749 if (PostThreadCondWait(lock, -1, [this] { return boot_finished_; })) {
750 return;
751 }
752
753 // Then, wait until we're either leaving the quiescent state, or the boot
754 // finished display off timeout expires.
755 if (PostThreadCondWait(lock, kBootFinishedDisplayOffTimeoutSec,
756 [this] { return !post_thread_quiescent_; })) {
757 return;
758 }
759
760 LOG_ALWAYS_FATAL_IF(post_thread_state_ & PostThreadState::Suspended,
761 "Vr flinger should own the display by now.");
762 post_thread_resumed_ = true;
763 post_thread_ready_.notify_all();
Steven Thomasbfe46a02018-02-16 14:27:35 -0800764 if (!composer_)
765 CreateComposer();
Steven Thomasaf336272018-01-04 17:36:47 -0800766 }
767
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800768 while (1) {
769 ATRACE_NAME("HardwareComposer::PostThread");
770
John Bates954796e2017-05-11 11:00:31 -0700771 // Check for updated config once per vsync.
772 UpdateConfigBuffer();
773
Corey Tabaka2251d822017-04-20 16:04:07 -0700774 while (post_thread_quiescent_) {
Steven Thomas050b2c82017-03-06 11:45:16 -0800775 std::unique_lock<std::mutex> lock(post_thread_mutex_);
Corey Tabaka2251d822017-04-20 16:04:07 -0700776 ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
777
Steven Thomasbfe46a02018-02-16 14:27:35 -0800778 // Tear down resources.
779 OnPostThreadPaused();
Corey Tabaka2251d822017-04-20 16:04:07 -0700780 was_running = false;
781 post_thread_resumed_ = false;
782 post_thread_ready_.notify_all();
783
Steven Thomasaf336272018-01-04 17:36:47 -0800784 if (PostThreadCondWait(lock, -1,
785 [this] { return !post_thread_quiescent_; })) {
786 // A true return value means we've been asked to quit.
Corey Tabaka2251d822017-04-20 16:04:07 -0700787 return;
Steven Thomas282a5ed2017-02-07 18:07:01 -0800788 }
Corey Tabaka2251d822017-04-20 16:04:07 -0700789
Corey Tabaka2251d822017-04-20 16:04:07 -0700790 post_thread_resumed_ = true;
791 post_thread_ready_.notify_all();
792
793 ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
Steven Thomas050b2c82017-03-06 11:45:16 -0800794 }
795
Steven Thomasbfe46a02018-02-16 14:27:35 -0800796 if (!composer_)
797 CreateComposer();
798
799 bool target_display_changed = UpdateTargetDisplay();
800 bool just_resumed_running = !was_running;
801 was_running = true;
802
803 if (target_display_changed)
804 vsync_eye_offsets = get_vsync_eye_offsets();
805
806 if (just_resumed_running) {
Steven Thomas050b2c82017-03-06 11:45:16 -0800807 OnPostThreadResumed();
Corey Tabaka2251d822017-04-20 16:04:07 -0700808
809 // Try to setup the scheduler policy if it failed during startup. Only
810 // attempt to do this on transitions from inactive to active to avoid
811 // spamming the system with RPCs and log messages.
812 if (!thread_policy_setup) {
813 thread_policy_setup =
814 SetThreadPolicy("graphics:high", "/system/performance");
815 }
Steven Thomasbfe46a02018-02-16 14:27:35 -0800816 }
Corey Tabakab3732f02017-09-16 00:58:54 -0700817
Steven Thomasbfe46a02018-02-16 14:27:35 -0800818 if (target_display_changed || just_resumed_running) {
Corey Tabakab3732f02017-09-16 00:58:54 -0700819 // Initialize the last vsync timestamp with the current time. The
820 // predictor below uses this time + the vsync interval in absolute time
821 // units for the initial delay. Once the driver starts reporting vsync the
822 // predictor will sync up with the real vsync.
823 last_vsync_timestamp_ = GetSystemClockNs();
Steven Thomasbfe46a02018-02-16 14:27:35 -0800824 vsync_prediction_interval_ = 1;
825 retire_fence_fds_.clear();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800826 }
827
828 int64_t vsync_timestamp = 0;
829 {
Corey Tabakab3732f02017-09-16 00:58:54 -0700830 TRACE_FORMAT("wait_vsync|vsync=%u;last_timestamp=%" PRId64
831 ";prediction_interval=%d|",
832 vsync_count_ + 1, last_vsync_timestamp_,
833 vsync_prediction_interval_);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800834
Steven Thomasbfe46a02018-02-16 14:27:35 -0800835 auto status = WaitForPredictedVSync();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800836 ALOGE_IF(
Corey Tabakab3732f02017-09-16 00:58:54 -0700837 !status,
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800838 "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
Corey Tabakab3732f02017-09-16 00:58:54 -0700839 status.GetErrorMessage().c_str());
840
841 // If there was an error either sleeping was interrupted due to pausing or
842 // there was an error getting the latest timestamp.
843 if (!status)
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800844 continue;
Corey Tabakab3732f02017-09-16 00:58:54 -0700845
846 // Predicted vsync timestamp for this interval. This is stable because we
847 // use absolute time for the wakeup timer.
848 vsync_timestamp = status.get();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800849 }
850
Corey Tabakab3732f02017-09-16 00:58:54 -0700851 // Advance the vsync counter only if the system is keeping up with hardware
852 // vsync to give clients an indication of the delays.
853 if (vsync_prediction_interval_ == 1)
854 ++vsync_count_;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800855
Steven Thomasbfe46a02018-02-16 14:27:35 -0800856 UpdateLayerConfig();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800857
Okan Arikan822b7102017-05-08 13:31:34 -0700858 // Publish the vsync event.
859 if (vsync_ring_) {
860 DvrVsync vsync;
861 vsync.vsync_count = vsync_count_;
862 vsync.vsync_timestamp_ns = vsync_timestamp;
Steven Thomasbfe46a02018-02-16 14:27:35 -0800863 vsync.vsync_left_eye_offset_ns = vsync_eye_offsets.left_ns;
864 vsync.vsync_right_eye_offset_ns = vsync_eye_offsets.right_ns;
865 vsync.vsync_period_ns = target_display_->vsync_period_ns;
Okan Arikan822b7102017-05-08 13:31:34 -0700866
867 vsync_ring_->Publish(vsync);
868 }
869
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800870 // Signal all of the vsync clients. Because absolute time is used for the
871 // wakeup time below, this can take a little time if necessary.
872 if (vsync_callback_)
Steven Thomas6e8f7062017-11-22 14:15:29 -0800873 vsync_callback_(vsync_timestamp, /*frame_time_estimate*/ 0, vsync_count_);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800874
875 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700876 // Sleep until shortly before vsync.
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800877 ATRACE_NAME("sleep");
878
Steven Thomasbfe46a02018-02-16 14:27:35 -0800879 const int64_t display_time_est_ns =
880 vsync_timestamp + target_display_->vsync_period_ns;
Corey Tabaka2251d822017-04-20 16:04:07 -0700881 const int64_t now_ns = GetSystemClockNs();
John Bates954796e2017-05-11 11:00:31 -0700882 const int64_t sleep_time_ns = display_time_est_ns - now_ns -
883 post_thread_config_.frame_post_offset_ns;
884 const int64_t wakeup_time_ns =
885 display_time_est_ns - post_thread_config_.frame_post_offset_ns;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800886
887 ATRACE_INT64("sleep_time_ns", sleep_time_ns);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800888 if (sleep_time_ns > 0) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700889 int error = SleepUntil(wakeup_time_ns);
John Bates46684842017-12-13 15:26:50 -0800890 ALOGE_IF(error < 0 && error != kPostThreadInterrupted,
891 "HardwareComposer::PostThread: Failed to sleep: %s",
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800892 strerror(-error));
John Bates46684842017-12-13 15:26:50 -0800893 // If the sleep was interrupted (error == kPostThreadInterrupted),
894 // we still go through and present this frame because we may have set
895 // layers earlier and we want to flush the Composer's internal command
896 // buffer by continuing through to validate and present.
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800897 }
898 }
899
Corey Tabakab3732f02017-09-16 00:58:54 -0700900 {
Steven Thomasbfe46a02018-02-16 14:27:35 -0800901 auto status = composer_callback_->GetVsyncTime(target_display_->id);
Corey Tabakab3732f02017-09-16 00:58:54 -0700902
903 // If we failed to read vsync there might be a problem with the driver.
904 // Since there's nothing we can do just behave as though we didn't get an
905 // updated vsync time and let the prediction continue.
906 const int64_t current_vsync_timestamp =
907 status ? status.get() : last_vsync_timestamp_;
908
909 const bool vsync_delayed =
910 last_vsync_timestamp_ == current_vsync_timestamp;
911 ATRACE_INT("vsync_delayed", vsync_delayed);
912
913 // If vsync was delayed advance the prediction interval and allow the
914 // fence logic in PostLayers() to skip the frame.
915 if (vsync_delayed) {
916 ALOGW(
917 "HardwareComposer::PostThread: VSYNC timestamp did not advance "
918 "since last frame: timestamp=%" PRId64 " prediction_interval=%d",
919 current_vsync_timestamp, vsync_prediction_interval_);
920 vsync_prediction_interval_++;
921 } else {
922 // We have an updated vsync timestamp, reset the prediction interval.
923 last_vsync_timestamp_ = current_vsync_timestamp;
924 vsync_prediction_interval_ = 1;
925 }
926 }
927
Steven Thomasbfe46a02018-02-16 14:27:35 -0800928 PostLayers(target_display_->id);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800929 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800930}
931
Steven Thomasbfe46a02018-02-16 14:27:35 -0800932bool HardwareComposer::UpdateTargetDisplay() {
933 bool target_display_changed = false;
934 auto displays = composer_callback_->GetDisplays();
935 if (displays.external_display_was_hotplugged) {
936 bool was_using_external_display = !target_display_->is_primary;
937 if (was_using_external_display) {
938 // The external display was hotplugged, so make sure to ignore any bad
939 // display errors as we destroy the layers.
940 for (auto& layer: layers_)
941 layer.IgnoreBadDisplayErrorsOnDestroy(true);
942 }
943
944 if (displays.external_display) {
945 // External display was connected
946 external_display_ = GetDisplayParams(composer_.get(),
947 *displays.external_display, /*is_primary*/ false);
948
949 if (property_get_bool(kUseExternalDisplayProperty, false)) {
950 ALOGI("External display connected. Switching to external display.");
951 target_display_ = &(*external_display_);
952 target_display_changed = true;
953 } else {
954 ALOGI("External display connected, but sysprop %s is unset, so"
955 " using primary display.", kUseExternalDisplayProperty);
956 if (was_using_external_display) {
957 target_display_ = &primary_display_;
958 target_display_changed = true;
959 }
960 }
961 } else {
962 // External display was disconnected
963 external_display_ = std::nullopt;
964 if (was_using_external_display) {
965 ALOGI("External display disconnected. Switching to primary display.");
966 target_display_ = &primary_display_;
967 target_display_changed = true;
968 }
969 }
970 }
971
972 if (target_display_changed) {
973 // If we're switching to the external display, turn the primary display off.
974 if (!target_display_->is_primary) {
975 EnableDisplay(primary_display_, false);
976 }
977 // If we're switching to the primary display, and the external display is
978 // still connected, turn the external display off.
979 else if (target_display_->is_primary && external_display_) {
980 EnableDisplay(*external_display_, false);
981 }
982
983 // Turn the new target display on.
984 EnableDisplay(*target_display_, true);
985
986 // When we switch displays we need to recreate all the layers, so clear the
987 // current list, which will trigger layer recreation.
988 layers_.clear();
989 }
990
991 return target_display_changed;
992}
993
Corey Tabaka2251d822017-04-20 16:04:07 -0700994// Checks for changes in the surface stack and updates the layer config to
995// accomodate the new stack.
Steven Thomasbfe46a02018-02-16 14:27:35 -0800996void HardwareComposer::UpdateLayerConfig() {
Corey Tabaka2251d822017-04-20 16:04:07 -0700997 std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
Steven Thomas050b2c82017-03-06 11:45:16 -0800998 {
Corey Tabaka2251d822017-04-20 16:04:07 -0700999 std::unique_lock<std::mutex> lock(post_thread_mutex_);
Corey Tabaka2251d822017-04-20 16:04:07 -07001000
Steven Thomasbfe46a02018-02-16 14:27:35 -08001001 if (!surfaces_changed_ && (!layers_.empty() || surfaces_.empty()))
1002 return;
1003
1004 surfaces = surfaces_;
1005 surfaces_changed_ = false;
Steven Thomas050b2c82017-03-06 11:45:16 -08001006 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001007
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001008 ATRACE_NAME("UpdateLayerConfig_HwLayers");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001009
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001010 // Sort the new direct surface list by z-order to determine the relative order
1011 // of the surfaces. This relative order is used for the HWC z-order value to
1012 // insulate VrFlinger and HWC z-order semantics from each other.
1013 std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) {
1014 return a->z_order() < b->z_order();
1015 });
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001016
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001017 // Prepare a new layer stack, pulling in layers from the previous
1018 // layer stack that are still active and updating their attributes.
1019 std::vector<Layer> layers;
1020 size_t layer_index = 0;
1021 for (const auto& surface : surfaces) {
Corey Tabaka2251d822017-04-20 16:04:07 -07001022 // The bottom layer is opaque, other layers blend.
1023 HWC::BlendMode blending =
1024 layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001025
1026 // Try to find a layer for this surface in the set of active layers.
1027 auto search =
1028 std::lower_bound(layers_.begin(), layers_.end(), surface->surface_id());
1029 const bool found = search != layers_.end() &&
1030 search->GetSurfaceId() == surface->surface_id();
1031 if (found) {
1032 // Update the attributes of the layer that may have changed.
1033 search->SetBlending(blending);
1034 search->SetZOrder(layer_index); // Relative z-order.
1035
1036 // Move the existing layer to the new layer set and remove the empty layer
1037 // object from the current set.
1038 layers.push_back(std::move(*search));
1039 layers_.erase(search);
1040 } else {
1041 // Insert a layer for the new surface.
Steven Thomasbfe46a02018-02-16 14:27:35 -08001042 layers.emplace_back(composer_.get(), *target_display_, surface, blending,
1043 HWC::Composition::Device, layer_index);
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001044 }
1045
1046 ALOGI_IF(
1047 TRACE,
1048 "HardwareComposer::UpdateLayerConfig: layer_index=%zu surface_id=%d",
1049 layer_index, layers[layer_index].GetSurfaceId());
1050
1051 layer_index++;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001052 }
1053
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001054 // Sort the new layer stack by ascending surface id.
1055 std::sort(layers.begin(), layers.end());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001056
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001057 // Replace the previous layer set with the new layer set. The destructor of
1058 // the previous set will clean up the remaining Layers that are not moved to
1059 // the new layer set.
1060 layers_ = std::move(layers);
1061
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001062 ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001063 layers_.size());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001064}
1065
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001066void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
1067 vsync_callback_ = callback;
1068}
1069
Steven Thomasb02664d2017-07-26 18:48:28 -07001070Return<void> HardwareComposer::ComposerCallback::onHotplug(
Steven Thomas6e8f7062017-11-22 14:15:29 -08001071 Hwc2::Display display, IComposerCallback::Connection conn) {
Steven Thomasbfe46a02018-02-16 14:27:35 -08001072 std::lock_guard<std::mutex> lock(mutex_);
1073 ALOGI("onHotplug display=%" PRIu64 " conn=%d", display, conn);
1074
1075 bool is_primary = !got_first_hotplug_ || display == primary_display_.id;
1076
Steven Thomas6e8f7062017-11-22 14:15:29 -08001077 // Our first onHotplug callback is always for the primary display.
Steven Thomasbfe46a02018-02-16 14:27:35 -08001078 if (!got_first_hotplug_) {
Steven Thomas6e8f7062017-11-22 14:15:29 -08001079 LOG_ALWAYS_FATAL_IF(conn != IComposerCallback::Connection::CONNECTED,
1080 "Initial onHotplug callback should be primary display connected");
Steven Thomasbfe46a02018-02-16 14:27:35 -08001081 got_first_hotplug_ = true;
1082 } else if (is_primary) {
1083 ALOGE("Ignoring unexpected onHotplug() call for primary display");
1084 return Void();
1085 }
1086
1087 if (conn == IComposerCallback::Connection::CONNECTED) {
1088 if (!is_primary)
1089 external_display_ = DisplayInfo();
1090 DisplayInfo& display_info = is_primary ?
1091 primary_display_ : *external_display_;
1092 display_info.id = display;
Steven Thomas6e8f7062017-11-22 14:15:29 -08001093
Corey Tabakab3732f02017-09-16 00:58:54 -07001094 std::array<char, 1024> buffer;
1095 snprintf(buffer.data(), buffer.size(),
1096 "/sys/class/graphics/fb%" PRIu64 "/vsync_event", display);
1097 if (LocalHandle handle{buffer.data(), O_RDONLY}) {
1098 ALOGI(
1099 "HardwareComposer::ComposerCallback::onHotplug: Driver supports "
1100 "vsync_event node for display %" PRIu64,
1101 display);
Steven Thomasbfe46a02018-02-16 14:27:35 -08001102 display_info.driver_vsync_event_fd = std::move(handle);
Corey Tabakab3732f02017-09-16 00:58:54 -07001103 } else {
1104 ALOGI(
1105 "HardwareComposer::ComposerCallback::onHotplug: Driver does not "
1106 "support vsync_event node for display %" PRIu64,
1107 display);
1108 }
Steven Thomasbfe46a02018-02-16 14:27:35 -08001109 } else if (conn == IComposerCallback::Connection::DISCONNECTED) {
1110 external_display_ = std::nullopt;
Corey Tabakab3732f02017-09-16 00:58:54 -07001111 }
1112
Steven Thomasbfe46a02018-02-16 14:27:35 -08001113 if (!is_primary)
1114 external_display_was_hotplugged_ = true;
1115
Steven Thomasb02664d2017-07-26 18:48:28 -07001116 return Void();
1117}
1118
1119Return<void> HardwareComposer::ComposerCallback::onRefresh(
1120 Hwc2::Display /*display*/) {
1121 return hardware::Void();
1122}
1123
Corey Tabaka451256f2017-08-22 11:59:15 -07001124Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display,
1125 int64_t timestamp) {
Steven Thomasbfe46a02018-02-16 14:27:35 -08001126 DisplayInfo* display_info = GetDisplayInfo(display);
1127 if (display_info) {
Steven Thomas6e8f7062017-11-22 14:15:29 -08001128 TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|",
1129 display, timestamp);
Steven Thomasbfe46a02018-02-16 14:27:35 -08001130 display_info->callback_vsync_timestamp = timestamp;
Steven Thomasb02664d2017-07-26 18:48:28 -07001131 }
Steven Thomasbfe46a02018-02-16 14:27:35 -08001132
Steven Thomasb02664d2017-07-26 18:48:28 -07001133 return Void();
1134}
1135
Steven Thomasbfe46a02018-02-16 14:27:35 -08001136HardwareComposer::ComposerCallback::Displays
1137HardwareComposer::ComposerCallback::GetDisplays() {
1138 std::lock_guard<std::mutex> lock(mutex_);
1139 Displays displays;
1140 displays.primary_display = primary_display_.id;
1141 if (external_display_)
1142 displays.external_display = external_display_->id;
1143 if (external_display_was_hotplugged_) {
1144 external_display_was_hotplugged_ = false;
1145 displays.external_display_was_hotplugged = true;
1146 }
1147 return displays;
1148}
1149
1150Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime(
1151 hwc2_display_t display) {
1152 DisplayInfo* display_info = GetDisplayInfo(display);
1153 if (!display_info) {
1154 ALOGW("Attempt to get vsync time for unknown display %" PRIu64, display);
1155 return ErrorStatus(EINVAL);
1156 }
1157
Corey Tabakab3732f02017-09-16 00:58:54 -07001158 // See if the driver supports direct vsync events.
Steven Thomasbfe46a02018-02-16 14:27:35 -08001159 LocalHandle& event_fd = display_info->driver_vsync_event_fd;
Corey Tabakab3732f02017-09-16 00:58:54 -07001160 if (!event_fd) {
1161 // Fall back to returning the last timestamp returned by the vsync
1162 // callback.
Steven Thomasbfe46a02018-02-16 14:27:35 -08001163 std::lock_guard<std::mutex> autolock(mutex_);
1164 return display_info->callback_vsync_timestamp;
Corey Tabakab3732f02017-09-16 00:58:54 -07001165 }
1166
1167 // When the driver supports the vsync_event sysfs node we can use it to
1168 // determine the latest vsync timestamp, even if the HWC callback has been
1169 // delayed.
1170
1171 // The driver returns data in the form "VSYNC=<timestamp ns>".
1172 std::array<char, 32> data;
1173 data.fill('\0');
1174
1175 // Seek back to the beginning of the event file.
1176 int ret = lseek(event_fd.Get(), 0, SEEK_SET);
1177 if (ret < 0) {
1178 const int error = errno;
1179 ALOGE(
1180 "HardwareComposer::ComposerCallback::GetVsyncTime: Failed to seek "
1181 "vsync event fd: %s",
1182 strerror(error));
1183 return ErrorStatus(error);
1184 }
1185
1186 // Read the vsync event timestamp.
1187 ret = read(event_fd.Get(), data.data(), data.size());
1188 if (ret < 0) {
1189 const int error = errno;
1190 ALOGE_IF(error != EAGAIN,
1191 "HardwareComposer::ComposerCallback::GetVsyncTime: Error "
1192 "while reading timestamp: %s",
1193 strerror(error));
1194 return ErrorStatus(error);
1195 }
1196
1197 int64_t timestamp;
1198 ret = sscanf(data.data(), "VSYNC=%" PRIu64,
1199 reinterpret_cast<uint64_t*>(&timestamp));
1200 if (ret < 0) {
1201 const int error = errno;
1202 ALOGE(
1203 "HardwareComposer::ComposerCallback::GetVsyncTime: Error while "
1204 "parsing timestamp: %s",
1205 strerror(error));
1206 return ErrorStatus(error);
1207 }
1208
1209 return {timestamp};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001210}
1211
Steven Thomasbfe46a02018-02-16 14:27:35 -08001212HardwareComposer::ComposerCallback::DisplayInfo*
1213HardwareComposer::ComposerCallback::GetDisplayInfo(hwc2_display_t display) {
1214 if (display == primary_display_.id) {
1215 return &primary_display_;
1216 } else if (external_display_ && display == external_display_->id) {
1217 return &(*external_display_);
1218 }
1219 return nullptr;
1220}
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001221
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001222void Layer::Reset() {
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001223 if (hardware_composer_layer_) {
Steven Thomasbfe46a02018-02-16 14:27:35 -08001224 HWC::Error error =
1225 composer_->destroyLayer(display_params_.id, hardware_composer_layer_);
1226 if (error != HWC::Error::None &&
1227 (!ignore_bad_display_errors_on_destroy_ ||
1228 error != HWC::Error::BadDisplay)) {
1229 ALOGE("destroyLayer() failed for display %" PRIu64 ", layer %" PRIu64
1230 ". error: %s", display_params_.id, hardware_composer_layer_,
1231 error.to_string().c_str());
1232 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001233 hardware_composer_layer_ = 0;
1234 }
1235
Corey Tabaka2251d822017-04-20 16:04:07 -07001236 z_order_ = 0;
1237 blending_ = HWC::BlendMode::None;
Corey Tabaka2251d822017-04-20 16:04:07 -07001238 composition_type_ = HWC::Composition::Invalid;
1239 target_composition_type_ = composition_type_;
1240 source_ = EmptyVariant{};
1241 acquire_fence_.Close();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001242 surface_rect_functions_applied_ = false;
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001243 pending_visibility_settings_ = true;
Corey Tabaka0d07cdd2017-09-28 11:15:50 -07001244 cached_buffer_map_.clear();
Steven Thomasbfe46a02018-02-16 14:27:35 -08001245 ignore_bad_display_errors_on_destroy_ = false;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001246}
1247
Steven Thomasbfe46a02018-02-16 14:27:35 -08001248Layer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params,
1249 const std::shared_ptr<DirectDisplaySurface>& surface,
1250 HWC::BlendMode blending, HWC::Composition composition_type,
1251 size_t z_order)
1252 : composer_(composer),
1253 display_params_(display_params),
1254 z_order_{z_order},
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001255 blending_{blending},
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001256 target_composition_type_{composition_type},
1257 source_{SourceSurface{surface}} {
1258 CommonLayerSetup();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001259}
1260
Steven Thomasbfe46a02018-02-16 14:27:35 -08001261Layer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params,
1262 const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
1263 HWC::Composition composition_type, size_t z_order)
1264 : composer_(composer),
1265 display_params_(display_params),
1266 z_order_{z_order},
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001267 blending_{blending},
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001268 target_composition_type_{composition_type},
1269 source_{SourceBuffer{buffer}} {
1270 CommonLayerSetup();
1271}
1272
1273Layer::~Layer() { Reset(); }
1274
1275Layer::Layer(Layer&& other) { *this = std::move(other); }
1276
1277Layer& Layer::operator=(Layer&& other) {
1278 if (this != &other) {
1279 Reset();
1280 using std::swap;
Steven Thomasbfe46a02018-02-16 14:27:35 -08001281 swap(composer_, other.composer_);
1282 swap(display_params_, other.display_params_);
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001283 swap(hardware_composer_layer_, other.hardware_composer_layer_);
1284 swap(z_order_, other.z_order_);
1285 swap(blending_, other.blending_);
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001286 swap(composition_type_, other.composition_type_);
1287 swap(target_composition_type_, other.target_composition_type_);
1288 swap(source_, other.source_);
1289 swap(acquire_fence_, other.acquire_fence_);
1290 swap(surface_rect_functions_applied_,
1291 other.surface_rect_functions_applied_);
1292 swap(pending_visibility_settings_, other.pending_visibility_settings_);
Corey Tabaka0d07cdd2017-09-28 11:15:50 -07001293 swap(cached_buffer_map_, other.cached_buffer_map_);
Steven Thomasbfe46a02018-02-16 14:27:35 -08001294 swap(ignore_bad_display_errors_on_destroy_,
1295 other.ignore_bad_display_errors_on_destroy_);
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001296 }
1297 return *this;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001298}
1299
Corey Tabaka2251d822017-04-20 16:04:07 -07001300void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
1301 if (source_.is<SourceBuffer>())
1302 std::get<SourceBuffer>(source_) = {buffer};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001303}
1304
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001305void Layer::SetBlending(HWC::BlendMode blending) {
1306 if (blending_ != blending) {
1307 blending_ = blending;
1308 pending_visibility_settings_ = true;
1309 }
1310}
1311
1312void Layer::SetZOrder(size_t z_order) {
1313 if (z_order_ != z_order) {
1314 z_order_ = z_order;
1315 pending_visibility_settings_ = true;
1316 }
1317}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001318
1319IonBuffer* Layer::GetBuffer() {
Corey Tabaka2251d822017-04-20 16:04:07 -07001320 struct Visitor {
1321 IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
1322 IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
1323 IonBuffer* operator()(EmptyVariant) { return nullptr; }
1324 };
1325 return source_.Visit(Visitor{});
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001326}
1327
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001328void Layer::UpdateVisibilitySettings() {
1329 if (pending_visibility_settings_) {
1330 pending_visibility_settings_ = false;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001331
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001332 HWC::Error error;
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001333
1334 error = composer_->setLayerBlendMode(
Steven Thomasbfe46a02018-02-16 14:27:35 -08001335 display_params_.id, hardware_composer_layer_,
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001336 blending_.cast<Hwc2::IComposerClient::BlendMode>());
1337 ALOGE_IF(error != HWC::Error::None,
1338 "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
1339 error.to_string().c_str());
1340
Steven Thomasbfe46a02018-02-16 14:27:35 -08001341 error = composer_->setLayerZOrder(display_params_.id,
1342 hardware_composer_layer_, z_order_);
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001343 ALOGE_IF(error != HWC::Error::None,
1344 "Layer::UpdateLayerSettings: Error setting z_ order: %s",
1345 error.to_string().c_str());
1346 }
1347}
1348
1349void Layer::UpdateLayerSettings() {
Corey Tabaka2251d822017-04-20 16:04:07 -07001350 HWC::Error error;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001351
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001352 UpdateVisibilitySettings();
1353
Corey Tabaka2251d822017-04-20 16:04:07 -07001354 // TODO(eieio): Use surface attributes or some other mechanism to control
1355 // the layer display frame.
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001356 error = composer_->setLayerDisplayFrame(
Steven Thomasbfe46a02018-02-16 14:27:35 -08001357 display_params_.id, hardware_composer_layer_,
1358 {0, 0, display_params_.width, display_params_.height});
Corey Tabaka2251d822017-04-20 16:04:07 -07001359 ALOGE_IF(error != HWC::Error::None,
1360 "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
1361 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001362
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001363 error = composer_->setLayerVisibleRegion(
Steven Thomasbfe46a02018-02-16 14:27:35 -08001364 display_params_.id, hardware_composer_layer_,
1365 {{0, 0, display_params_.width, display_params_.height}});
Corey Tabaka2251d822017-04-20 16:04:07 -07001366 ALOGE_IF(error != HWC::Error::None,
1367 "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
1368 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001369
Steven Thomasbfe46a02018-02-16 14:27:35 -08001370 error = composer_->setLayerPlaneAlpha(display_params_.id,
1371 hardware_composer_layer_, 1.0f);
Corey Tabaka2251d822017-04-20 16:04:07 -07001372 ALOGE_IF(error != HWC::Error::None,
1373 "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
1374 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001375}
1376
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001377void Layer::CommonLayerSetup() {
Steven Thomasbfe46a02018-02-16 14:27:35 -08001378 HWC::Error error = composer_->createLayer(display_params_.id,
Steven Thomas6e8f7062017-11-22 14:15:29 -08001379 &hardware_composer_layer_);
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001380 ALOGE_IF(error != HWC::Error::None,
1381 "Layer::CommonLayerSetup: Failed to create layer on primary "
1382 "display: %s",
1383 error.to_string().c_str());
1384 UpdateLayerSettings();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001385}
1386
Corey Tabaka0d07cdd2017-09-28 11:15:50 -07001387bool Layer::CheckAndUpdateCachedBuffer(std::size_t slot, int buffer_id) {
1388 auto search = cached_buffer_map_.find(slot);
1389 if (search != cached_buffer_map_.end() && search->second == buffer_id)
1390 return true;
1391
1392 // Assign or update the buffer slot.
1393 if (buffer_id >= 0)
1394 cached_buffer_map_[slot] = buffer_id;
1395 return false;
1396}
1397
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001398void Layer::Prepare() {
Corey Tabaka0d07cdd2017-09-28 11:15:50 -07001399 int right, bottom, id;
Daniel Nicoara1f42e3a2017-04-10 13:27:32 -04001400 sp<GraphicBuffer> handle;
Corey Tabaka0d07cdd2017-09-28 11:15:50 -07001401 std::size_t slot;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001402
Corey Tabaka2251d822017-04-20 16:04:07 -07001403 // Acquire the next buffer according to the type of source.
1404 IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
Corey Tabaka0d07cdd2017-09-28 11:15:50 -07001405 std::tie(right, bottom, id, handle, acquire_fence_, slot) =
1406 source.Acquire();
Corey Tabaka2251d822017-04-20 16:04:07 -07001407 });
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001408
Corey Tabaka0d07cdd2017-09-28 11:15:50 -07001409 TRACE_FORMAT("Layer::Prepare|buffer_id=%d;slot=%zu|", id, slot);
1410
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001411 // Update any visibility (blending, z-order) changes that occurred since
1412 // last prepare.
1413 UpdateVisibilitySettings();
1414
1415 // When a layer is first setup there may be some time before the first
1416 // buffer arrives. Setup the HWC layer as a solid color to stall for time
1417 // until the first buffer arrives. Once the first buffer arrives there will
1418 // always be a buffer for the frame even if it is old.
Corey Tabaka2251d822017-04-20 16:04:07 -07001419 if (!handle.get()) {
1420 if (composition_type_ == HWC::Composition::Invalid) {
1421 composition_type_ = HWC::Composition::SolidColor;
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001422 composer_->setLayerCompositionType(
Steven Thomasbfe46a02018-02-16 14:27:35 -08001423 display_params_.id, hardware_composer_layer_,
Corey Tabaka2251d822017-04-20 16:04:07 -07001424 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1425 Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
Steven Thomasbfe46a02018-02-16 14:27:35 -08001426 composer_->setLayerColor(display_params_.id, hardware_composer_layer_,
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001427 layer_color);
Corey Tabaka2251d822017-04-20 16:04:07 -07001428 } else {
1429 // The composition type is already set. Nothing else to do until a
1430 // buffer arrives.
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001431 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001432 } else {
Corey Tabaka2251d822017-04-20 16:04:07 -07001433 if (composition_type_ != target_composition_type_) {
1434 composition_type_ = target_composition_type_;
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001435 composer_->setLayerCompositionType(
Steven Thomasbfe46a02018-02-16 14:27:35 -08001436 display_params_.id, hardware_composer_layer_,
Corey Tabaka2251d822017-04-20 16:04:07 -07001437 composition_type_.cast<Hwc2::IComposerClient::Composition>());
1438 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001439
Corey Tabaka0d07cdd2017-09-28 11:15:50 -07001440 // See if the HWC cache already has this buffer.
1441 const bool cached = CheckAndUpdateCachedBuffer(slot, id);
1442 if (cached)
1443 handle = nullptr;
1444
Corey Tabaka2251d822017-04-20 16:04:07 -07001445 HWC::Error error{HWC::Error::None};
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001446 error =
Steven Thomasbfe46a02018-02-16 14:27:35 -08001447 composer_->setLayerBuffer(display_params_.id, hardware_composer_layer_,
Corey Tabaka0d07cdd2017-09-28 11:15:50 -07001448 slot, handle, acquire_fence_.Get());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001449
Corey Tabaka2251d822017-04-20 16:04:07 -07001450 ALOGE_IF(error != HWC::Error::None,
1451 "Layer::Prepare: Error setting layer buffer: %s",
1452 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001453
Corey Tabaka2251d822017-04-20 16:04:07 -07001454 if (!surface_rect_functions_applied_) {
1455 const float float_right = right;
1456 const float float_bottom = bottom;
Steven Thomasbfe46a02018-02-16 14:27:35 -08001457 error = composer_->setLayerSourceCrop(display_params_.id,
Corey Tabaka2c4aea32017-08-31 20:01:15 -07001458 hardware_composer_layer_,
1459 {0, 0, float_right, float_bottom});
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001460
Corey Tabaka2251d822017-04-20 16:04:07 -07001461 ALOGE_IF(error != HWC::Error::None,
1462 "Layer::Prepare: Error setting layer source crop: %s",
1463 error.to_string().c_str());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001464
Corey Tabaka2251d822017-04-20 16:04:07 -07001465 surface_rect_functions_applied_ = true;
1466 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001467 }
1468}
1469
1470void Layer::Finish(int release_fence_fd) {
Corey Tabaka2251d822017-04-20 16:04:07 -07001471 IfAnyOf<SourceSurface, SourceBuffer>::Call(
1472 &source_, [release_fence_fd](auto& source) {
1473 source.Finish(LocalHandle(release_fence_fd));
1474 });
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001475}
1476
Corey Tabaka2251d822017-04-20 16:04:07 -07001477void Layer::Drop() { acquire_fence_.Close(); }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001478
1479} // namespace dvr
1480} // namespace android