| Alex Vakulenko | a8a9278 | 2017-01-27 14:41:57 -0800 | [diff] [blame] | 1 | #include "hardware_composer.h" | 
|  | 2 |  | 
|  | 3 | #include <log/log.h> | 
|  | 4 | #include <cutils/properties.h> | 
|  | 5 | #include <cutils/sched_policy.h> | 
|  | 6 | #include <fcntl.h> | 
|  | 7 | #include <poll.h> | 
|  | 8 | #include <sync/sync.h> | 
|  | 9 | #include <sys/eventfd.h> | 
|  | 10 | #include <sys/prctl.h> | 
|  | 11 | #include <sys/resource.h> | 
|  | 12 | #include <sys/system_properties.h> | 
|  | 13 | #include <sys/timerfd.h> | 
|  | 14 | #include <unistd.h> | 
|  | 15 | #include <utils/Trace.h> | 
|  | 16 |  | 
|  | 17 | #include <algorithm> | 
|  | 18 | #include <functional> | 
|  | 19 | #include <map> | 
|  | 20 |  | 
|  | 21 | #include <dvr/performance_client_api.h> | 
|  | 22 | #include <private/dvr/clock_ns.h> | 
|  | 23 | #include <private/dvr/display_types.h> | 
|  | 24 | #include <private/dvr/pose_client_internal.h> | 
|  | 25 | #include <private/dvr/sync_util.h> | 
|  | 26 |  | 
|  | 27 | #include "debug_hud_data.h" | 
|  | 28 | #include "screenshot_service.h" | 
|  | 29 |  | 
|  | 30 | using android::pdx::LocalHandle; | 
|  | 31 |  | 
|  | 32 | namespace android { | 
|  | 33 | namespace dvr { | 
|  | 34 |  | 
|  | 35 | namespace { | 
|  | 36 |  | 
|  | 37 | // If the number of pending fences goes over this count at the point when we | 
|  | 38 | // are about to submit a new frame to HWC, we will drop the frame. This should | 
|  | 39 | // be a signal that the display driver has begun queuing frames. Note that with | 
|  | 40 | // smart displays (with RAM), the fence is signaled earlier than the next vsync, | 
|  | 41 | // at the point when the DMA to the display completes. Currently we use a smart | 
|  | 42 | // display and the EDS timing coincides with zero pending fences, so this is 0. | 
|  | 43 | constexpr int kAllowedPendingFenceCount = 0; | 
|  | 44 |  | 
|  | 45 | // If we think we're going to miss vsync by more than this amount, skip the | 
|  | 46 | // frame. | 
|  | 47 | constexpr int64_t kFrameSkipThresholdNs = 4000000;  // 4ms | 
|  | 48 |  | 
|  | 49 | // Counter PostLayers() deficiency by requiring apps to produce a frame at least | 
|  | 50 | // 2.5ms before vsync. See b/28881672. | 
|  | 51 | constexpr int64_t kFrameTimeEstimateMin = 2500000;  // 2.5ms | 
|  | 52 |  | 
|  | 53 | constexpr size_t kDefaultDisplayConfigCount = 32; | 
|  | 54 |  | 
|  | 55 | constexpr float kMetersPerInch = 0.0254f; | 
|  | 56 |  | 
|  | 57 | const char kBacklightBrightnessSysFile[] = | 
|  | 58 | "/sys/class/leds/lcd-backlight/brightness"; | 
|  | 59 |  | 
|  | 60 | const char kPrimaryDisplayVSyncEventFile[] = | 
|  | 61 | "/sys/class/graphics/fb0/vsync_event"; | 
|  | 62 |  | 
|  | 63 | const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp"; | 
|  | 64 |  | 
|  | 65 | const char kDvrPerformanceProperty[] = "sys.dvr.performance"; | 
|  | 66 |  | 
|  | 67 | const char kRightEyeOffsetProperty[] = "dreamos.right_eye_offset_ns"; | 
|  | 68 |  | 
|  | 69 | // Returns our best guess for the time the compositor will spend rendering the | 
|  | 70 | // next frame. | 
|  | 71 | int64_t GuessFrameTime(int compositor_visible_layer_count) { | 
|  | 72 | // The cost of asynchronous EDS and lens warp is currently measured at 2.5ms | 
|  | 73 | // for one layer and 7ms for two layers, but guess a higher frame time to | 
|  | 74 | // account for CPU overhead. This guess is only used before we've measured the | 
|  | 75 | // actual time to render a frame for the current compositor configuration. | 
|  | 76 | switch (compositor_visible_layer_count) { | 
|  | 77 | case 0: | 
|  | 78 | return 500000;  // .5ms | 
|  | 79 | case 1: | 
|  | 80 | return 5000000;  // 5ms | 
|  | 81 | default: | 
|  | 82 | return 10500000;  // 10.5ms | 
|  | 83 | } | 
|  | 84 | } | 
|  | 85 |  | 
|  | 86 | // Get time offset from a vsync to when the pose for that vsync should be | 
|  | 87 | // predicted out to. For example, if scanout gets halfway through the frame | 
|  | 88 | // at the halfway point between vsyncs, then this could be half the period. | 
|  | 89 | // With global shutter displays, this should be changed to the offset to when | 
|  | 90 | // illumination begins. Low persistence adds a frame of latency, so we predict | 
|  | 91 | // to the center of the next frame. | 
|  | 92 | inline int64_t GetPosePredictionTimeOffset(int64_t vsync_period_ns) { | 
|  | 93 | return (vsync_period_ns * 150) / 100; | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | }  // anonymous namespace | 
|  | 97 |  | 
|  | 98 | HardwareComposer::HardwareComposer() | 
|  | 99 | : HardwareComposer(nullptr) { | 
|  | 100 | } | 
|  | 101 |  | 
|  | 102 | HardwareComposer::HardwareComposer(Hwc2::Composer* hwc2_hidl) | 
|  | 103 | : hwc2_hidl_(hwc2_hidl), | 
|  | 104 | display_transform_(HWC_TRANSFORM_NONE), | 
|  | 105 | display_surfaces_updated_(false), | 
|  | 106 | hardware_layers_need_update_(false), | 
| Alex Vakulenko | a8a9278 | 2017-01-27 14:41:57 -0800 | [diff] [blame] | 107 | active_layer_count_(0), | 
|  | 108 | gpu_layer_(nullptr), | 
|  | 109 | terminate_post_thread_event_fd_(-1), | 
|  | 110 | pause_post_thread_(true), | 
|  | 111 | backlight_brightness_fd_(-1), | 
|  | 112 | primary_display_vsync_event_fd_(-1), | 
|  | 113 | primary_display_wait_pp_fd_(-1), | 
|  | 114 | vsync_sleep_timer_fd_(-1), | 
|  | 115 | last_vsync_timestamp_(0), | 
|  | 116 | vsync_count_(0), | 
|  | 117 | frame_skip_count_(0), | 
|  | 118 | pose_client_(nullptr) { | 
|  | 119 | std::transform(layer_storage_.begin(), layer_storage_.end(), layers_.begin(), | 
|  | 120 | [](auto& layer) { return &layer; }); | 
|  | 121 |  | 
|  | 122 | callbacks_ = new ComposerCallback; | 
|  | 123 | } | 
|  | 124 |  | 
|  | 125 | HardwareComposer::~HardwareComposer(void) { | 
|  | 126 | if (!IsSuspended()) { | 
|  | 127 | Suspend(); | 
|  | 128 | } | 
|  | 129 | } | 
|  | 130 |  | 
|  | 131 | bool HardwareComposer::Resume() { | 
|  | 132 | std::lock_guard<std::mutex> autolock(layer_mutex_); | 
|  | 133 |  | 
|  | 134 | if (!IsSuspended()) { | 
|  | 135 | ALOGE("HardwareComposer::Resume: HardwareComposer is already running."); | 
|  | 136 | return false; | 
|  | 137 | } | 
|  | 138 |  | 
|  | 139 | int32_t ret = HWC2_ERROR_NONE; | 
|  | 140 |  | 
|  | 141 | static const uint32_t attributes[] = { | 
|  | 142 | HWC_DISPLAY_WIDTH, HWC_DISPLAY_HEIGHT, HWC_DISPLAY_VSYNC_PERIOD, | 
|  | 143 | HWC_DISPLAY_DPI_X, HWC_DISPLAY_DPI_Y,  HWC_DISPLAY_NO_ATTRIBUTE, | 
|  | 144 | }; | 
|  | 145 |  | 
|  | 146 | std::vector<Hwc2::Config> configs; | 
|  | 147 | ret = (int32_t)hwc2_hidl_->getDisplayConfigs(HWC_DISPLAY_PRIMARY, &configs); | 
|  | 148 |  | 
|  | 149 | if (ret != HWC2_ERROR_NONE) { | 
|  | 150 | ALOGE("HardwareComposer: Failed to get display configs"); | 
|  | 151 | return false; | 
|  | 152 | } | 
|  | 153 |  | 
|  | 154 | uint32_t num_configs = configs.size(); | 
|  | 155 |  | 
|  | 156 | for (size_t i = 0; i < num_configs; i++) { | 
|  | 157 | ALOGI("HardwareComposer: cfg[%zd/%zd] = 0x%08x", i, num_configs, | 
|  | 158 | configs[i]); | 
|  | 159 |  | 
|  | 160 | ret = GetDisplayMetrics(HWC_DISPLAY_PRIMARY, configs[i], | 
|  | 161 | &native_display_metrics_); | 
|  | 162 |  | 
|  | 163 | if (ret != HWC2_ERROR_NONE) { | 
|  | 164 | ALOGE("HardwareComposer: Failed to get display attributes %d", ret); | 
|  | 165 | continue; | 
|  | 166 | } else { | 
|  | 167 | ret = | 
|  | 168 | (int32_t)hwc2_hidl_->setActiveConfig(HWC_DISPLAY_PRIMARY, configs[i]); | 
|  | 169 |  | 
|  | 170 | if (ret != HWC2_ERROR_NONE) { | 
|  | 171 | ALOGE("HardwareComposer: Failed to set display configuration; ret=%d", | 
|  | 172 | ret); | 
|  | 173 | continue; | 
|  | 174 | } | 
|  | 175 |  | 
|  | 176 | break; | 
|  | 177 | } | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | if (ret != HWC2_ERROR_NONE) { | 
|  | 181 | ALOGE("HardwareComposer: Could not set a valid display configuration."); | 
|  | 182 | return false; | 
|  | 183 | } | 
|  | 184 |  | 
|  | 185 | // Set the display metrics but never use rotation to avoid the long latency of | 
|  | 186 | // rotation processing in hwc. | 
|  | 187 | display_transform_ = HWC_TRANSFORM_NONE; | 
|  | 188 | display_metrics_ = native_display_metrics_; | 
|  | 189 |  | 
|  | 190 | ALOGI( | 
|  | 191 | "HardwareComposer: primary display attributes: width=%d height=%d " | 
|  | 192 | "vsync_period_ns=%d DPI=%dx%d", | 
|  | 193 | native_display_metrics_.width, native_display_metrics_.height, | 
|  | 194 | native_display_metrics_.vsync_period_ns, native_display_metrics_.dpi.x, | 
|  | 195 | native_display_metrics_.dpi.y); | 
|  | 196 |  | 
|  | 197 | // Always turn off vsync when we start. | 
|  | 198 | EnableVsync(false); | 
|  | 199 |  | 
|  | 200 | constexpr int format = HAL_PIXEL_FORMAT_RGBA_8888; | 
|  | 201 | constexpr int usage = | 
|  | 202 | GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER; | 
|  | 203 |  | 
|  | 204 | framebuffer_target_ = std::make_shared<IonBuffer>( | 
|  | 205 | native_display_metrics_.width, native_display_metrics_.height, format, | 
|  | 206 | usage); | 
|  | 207 |  | 
|  | 208 | // Associate each Layer instance with a hardware composer layer. | 
|  | 209 | for (auto layer : layers_) { | 
|  | 210 | layer->Initialize(hwc2_hidl_.get(), &native_display_metrics_); | 
|  | 211 | } | 
|  | 212 |  | 
| Hendrik Wagenaar | ea57242 | 2017-02-02 10:00:48 -0800 | [diff] [blame] | 213 | #if ENABLE_BACKLIGHT_BRIGHTNESS | 
|  | 214 | // TODO(hendrikw): This isn't required at the moment. It's possible that there | 
|  | 215 | //                 is another method to access this when needed. | 
| Alex Vakulenko | a8a9278 | 2017-01-27 14:41:57 -0800 | [diff] [blame] | 216 | // Open the backlight brightness control sysfs node. | 
|  | 217 | backlight_brightness_fd_ = LocalHandle(kBacklightBrightnessSysFile, O_RDWR); | 
|  | 218 | ALOGW_IF(!backlight_brightness_fd_, | 
|  | 219 | "HardwareComposer: Failed to open backlight brightness control: %s", | 
|  | 220 | strerror(errno)); | 
| Hendrik Wagenaar | ea57242 | 2017-02-02 10:00:48 -0800 | [diff] [blame] | 221 | #endif // ENABLE_BACKLIGHT_BRIGHTNESS | 
| Alex Vakulenko | a8a9278 | 2017-01-27 14:41:57 -0800 | [diff] [blame] | 222 |  | 
|  | 223 | // Open the vsync event node for the primary display. | 
|  | 224 | // TODO(eieio): Move this into a platform-specific class. | 
|  | 225 | primary_display_vsync_event_fd_ = | 
|  | 226 | LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY); | 
|  | 227 | ALOGE_IF(!primary_display_vsync_event_fd_, | 
|  | 228 | "HardwareComposer: Failed to open vsync event node for primary " | 
|  | 229 | "display: %s", | 
|  | 230 | strerror(errno)); | 
|  | 231 |  | 
|  | 232 | // Open the wait pingpong status node for the primary display. | 
|  | 233 | // TODO(eieio): Move this into a platform-specific class. | 
|  | 234 | primary_display_wait_pp_fd_ = | 
|  | 235 | LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY); | 
|  | 236 | ALOGE_IF( | 
|  | 237 | !primary_display_wait_pp_fd_, | 
|  | 238 | "HardwareComposer: Failed to open wait_pp node for primary display: %s", | 
|  | 239 | strerror(errno)); | 
|  | 240 |  | 
|  | 241 | // Create a timerfd based on CLOCK_MONOTINIC. | 
|  | 242 | vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0)); | 
|  | 243 | LOG_ALWAYS_FATAL_IF( | 
|  | 244 | !vsync_sleep_timer_fd_, | 
|  | 245 | "HardwareComposer: Failed to create vsync sleep timerfd: %s", | 
|  | 246 | strerror(errno)); | 
|  | 247 |  | 
|  | 248 | // Connect to pose service. | 
|  | 249 | pose_client_ = dvrPoseCreate(); | 
|  | 250 | ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client"); | 
|  | 251 |  | 
|  | 252 | // Variables used to control the post thread state | 
|  | 253 | pause_post_thread_ = false; | 
|  | 254 | terminate_post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); | 
|  | 255 |  | 
|  | 256 | LOG_ALWAYS_FATAL_IF( | 
|  | 257 | !terminate_post_thread_event_fd_, | 
|  | 258 | "HardwareComposer: Failed to create terminate PostThread event fd : %s", | 
|  | 259 | strerror(errno)); | 
|  | 260 |  | 
|  | 261 | // If get_id() is the default thread::id object, it has not been created yet | 
|  | 262 | if (post_thread_.get_id() == std::thread::id()) { | 
|  | 263 | post_thread_ = std::thread(&HardwareComposer::PostThread, this); | 
|  | 264 | } else { | 
|  | 265 | UpdateDisplayState(); | 
|  | 266 | thread_pause_semaphore_.notify_one(); | 
|  | 267 | } | 
|  | 268 |  | 
|  | 269 | return true; | 
|  | 270 | } | 
|  | 271 |  | 
|  | 272 | bool HardwareComposer::Suspend() { | 
|  | 273 | // Wait for any pending layer operations to finish | 
|  | 274 | std::unique_lock<std::mutex> layer_lock(layer_mutex_); | 
|  | 275 |  | 
|  | 276 | if (IsSuspended()) { | 
|  | 277 | ALOGE("HardwareComposer::Suspend: HardwareComposer is already suspended."); | 
|  | 278 | return false; | 
|  | 279 | } | 
|  | 280 |  | 
|  | 281 | PausePostThread(); | 
|  | 282 |  | 
|  | 283 | EnableVsync(false); | 
| Alex Vakulenko | a8a9278 | 2017-01-27 14:41:57 -0800 | [diff] [blame] | 284 |  | 
|  | 285 | backlight_brightness_fd_.Close(); | 
|  | 286 | primary_display_vsync_event_fd_.Close(); | 
|  | 287 | primary_display_wait_pp_fd_.Close(); | 
|  | 288 | vsync_sleep_timer_fd_.Close(); | 
|  | 289 | retire_fence_fds_.clear(); | 
|  | 290 | gpu_layer_ = nullptr; | 
|  | 291 |  | 
|  | 292 | // We have to destroy the layers before we close the hwc device | 
|  | 293 | for (size_t i = 0; i < kMaxHardwareLayers; ++i) { | 
|  | 294 | layers_[i]->Reset(); | 
|  | 295 | } | 
|  | 296 |  | 
|  | 297 | active_layer_count_ = 0; | 
|  | 298 |  | 
|  | 299 | framebuffer_target_.reset(); | 
|  | 300 |  | 
|  | 301 | //hwc2_hidl_.reset(); | 
|  | 302 |  | 
|  | 303 | if (pose_client_) | 
|  | 304 | dvrPoseDestroy(pose_client_); | 
|  | 305 |  | 
|  | 306 | return true; | 
|  | 307 | } | 
|  | 308 |  | 
|  | 309 | void HardwareComposer::PausePostThread() { | 
|  | 310 | pause_post_thread_ = true; | 
|  | 311 |  | 
|  | 312 | int error = eventfd_write(terminate_post_thread_event_fd_.Get(), 1); | 
|  | 313 | ALOGE_IF(error, | 
|  | 314 | "HardwareComposer::PausePostThread: could not write post " | 
|  | 315 | "thread termination event fd : %d", | 
|  | 316 | error); | 
|  | 317 |  | 
|  | 318 | std::unique_lock<std::mutex> wait_for_thread(thread_pause_mutex_); | 
|  | 319 | terminate_post_thread_event_fd_.Close(); | 
|  | 320 | } | 
|  | 321 |  | 
|  | 322 | DisplayMetrics HardwareComposer::GetHmdDisplayMetrics() const { | 
|  | 323 | vec2i screen_size(display_metrics_.width, display_metrics_.height); | 
|  | 324 | DisplayOrientation orientation = | 
|  | 325 | (display_metrics_.width > display_metrics_.height | 
|  | 326 | ? DisplayOrientation::kLandscape | 
|  | 327 | : DisplayOrientation::kPortrait); | 
|  | 328 | float dpi_x = static_cast<float>(display_metrics_.dpi.x) / 1000.0f; | 
|  | 329 | float dpi_y = static_cast<float>(display_metrics_.dpi.y) / 1000.0f; | 
|  | 330 | float meters_per_pixel_x = kMetersPerInch / dpi_x; | 
|  | 331 | float meters_per_pixel_y = kMetersPerInch / dpi_y; | 
|  | 332 | vec2 meters_per_pixel(meters_per_pixel_x, meters_per_pixel_y); | 
|  | 333 | double frame_duration_s = | 
|  | 334 | static_cast<double>(display_metrics_.vsync_period_ns) / 1000000000.0; | 
|  | 335 | // TODO(hendrikw): Hard coding to 3mm.  The Pixel is actually 4mm, but it | 
|  | 336 | //                 seems that their tray to lens distance is wrong too, which | 
|  | 337 | //                 offsets this, at least for the pixel. | 
|  | 338 | float border_size = 0.003f; | 
|  | 339 | return DisplayMetrics(screen_size, meters_per_pixel, border_size, | 
|  | 340 | static_cast<float>(frame_duration_s), orientation); | 
|  | 341 | } | 
|  | 342 |  | 
|  | 343 | int32_t HardwareComposer::Validate(hwc2_display_t display) { | 
|  | 344 | uint32_t num_types; | 
|  | 345 | uint32_t num_requests; | 
|  | 346 | int32_t error = | 
|  | 347 | (int32_t)hwc2_hidl_->validateDisplay(display, &num_types, &num_requests); | 
|  | 348 |  | 
|  | 349 | if (error == HWC2_ERROR_HAS_CHANGES) { | 
|  | 350 | // TODO(skiazyk): We might need to inspect the requested changes first, but | 
|  | 351 | // so far it seems like we shouldn't ever hit a bad state. | 
|  | 352 | // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_, | 
|  | 353 | //                                               display); | 
|  | 354 | error = (int32_t)hwc2_hidl_->acceptDisplayChanges(display); | 
|  | 355 | } | 
|  | 356 |  | 
|  | 357 | return error; | 
|  | 358 | } | 
|  | 359 |  | 
|  | 360 | int32_t HardwareComposer::EnableVsync(bool enabled) { | 
|  | 361 | return (int32_t)hwc2_hidl_->setVsyncEnabled( | 
|  | 362 | HWC_DISPLAY_PRIMARY, | 
|  | 363 | (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE | 
|  | 364 | : HWC2_VSYNC_DISABLE)); | 
|  | 365 | } | 
|  | 366 |  | 
|  | 367 | int32_t HardwareComposer::Present(hwc2_display_t display) { | 
|  | 368 | int32_t present_fence; | 
|  | 369 | int32_t error = (int32_t)hwc2_hidl_->presentDisplay(display, &present_fence); | 
|  | 370 |  | 
|  | 371 | // According to the documentation, this fence is signaled at the time of | 
|  | 372 | // vsync/DMA for physical displays. | 
|  | 373 | if (error == HWC2_ERROR_NONE) { | 
|  | 374 | ATRACE_INT("HardwareComposer: VsyncFence", present_fence); | 
|  | 375 | retire_fence_fds_.emplace_back(present_fence); | 
|  | 376 | } else { | 
|  | 377 | ATRACE_INT("HardwareComposer: PresentResult", error); | 
|  | 378 | } | 
|  | 379 |  | 
|  | 380 | return error; | 
|  | 381 | } | 
|  | 382 |  | 
| Alex Vakulenko | a8a9278 | 2017-01-27 14:41:57 -0800 | [diff] [blame] | 383 | int32_t HardwareComposer::GetDisplayAttribute(hwc2_display_t display, | 
|  | 384 | hwc2_config_t config, | 
|  | 385 | hwc2_attribute_t attribute, | 
|  | 386 | int32_t* out_value) const { | 
|  | 387 | return (int32_t)hwc2_hidl_->getDisplayAttribute( | 
|  | 388 | display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value); | 
|  | 389 | } | 
|  | 390 |  | 
|  | 391 | int32_t HardwareComposer::GetDisplayMetrics( | 
|  | 392 | hwc2_display_t display, hwc2_config_t config, | 
|  | 393 | HWCDisplayMetrics* out_metrics) const { | 
|  | 394 | int32_t ret = HWC2_ERROR_NONE; | 
|  | 395 |  | 
|  | 396 | ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH, | 
|  | 397 | &out_metrics->width); | 
|  | 398 | if (ret != HWC2_ERROR_NONE) { | 
|  | 399 | ALOGE("HardwareComposer: Failed to get display width"); | 
|  | 400 | return ret; | 
|  | 401 | } | 
|  | 402 |  | 
|  | 403 | ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT, | 
|  | 404 | &out_metrics->height); | 
|  | 405 | if (ret != HWC2_ERROR_NONE) { | 
|  | 406 | ALOGE("HardwareComposer: Failed to get display height"); | 
|  | 407 | return ret; | 
|  | 408 | } | 
|  | 409 |  | 
|  | 410 | ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD, | 
|  | 411 | &out_metrics->vsync_period_ns); | 
|  | 412 | if (ret != HWC2_ERROR_NONE) { | 
|  | 413 | ALOGE("HardwareComposer: Failed to get display height"); | 
|  | 414 | return ret; | 
|  | 415 | } | 
|  | 416 |  | 
|  | 417 | ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X, | 
|  | 418 | &out_metrics->dpi.x); | 
|  | 419 | if (ret != HWC2_ERROR_NONE) { | 
|  | 420 | ALOGE("HardwareComposer: Failed to get display DPI X"); | 
|  | 421 | return ret; | 
|  | 422 | } | 
|  | 423 |  | 
|  | 424 | ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y, | 
|  | 425 | &out_metrics->dpi.y); | 
|  | 426 | if (ret != HWC2_ERROR_NONE) { | 
|  | 427 | ALOGE("HardwareComposer: Failed to get display DPI Y"); | 
|  | 428 | return ret; | 
|  | 429 | } | 
|  | 430 |  | 
|  | 431 | return HWC2_ERROR_NONE; | 
|  | 432 | } | 
|  | 433 |  | 
|  | 434 | void HardwareComposer::Dump(char* buffer, uint32_t* out_size) { | 
|  | 435 | std::string debug_str = hwc2_hidl_->dumpDebugInfo(); | 
|  | 436 | ALOGI("%s", debug_str.c_str()); | 
|  | 437 |  | 
|  | 438 | if (buffer == nullptr) { | 
|  | 439 | *out_size = debug_str.size(); | 
|  | 440 | } else { | 
|  | 441 | std::copy(debug_str.begin(), debug_str.begin() + *out_size, buffer); | 
|  | 442 | } | 
|  | 443 | } | 
|  | 444 |  | 
|  | 445 | // TODO(skiazyk): Figure out what to do with `is_geometry_changed`. There does | 
|  | 446 | // not seem to be any equivalent in the HWC2 API, but that doesn't mean its not | 
|  | 447 | // there. | 
|  | 448 | void HardwareComposer::PostLayers(bool /*is_geometry_changed*/) { | 
|  | 449 | ATRACE_NAME("HardwareComposer::PostLayers"); | 
|  | 450 |  | 
|  | 451 | // Setup the hardware composer layers with current buffers. | 
|  | 452 | for (size_t i = 0; i < active_layer_count_; i++) { | 
|  | 453 | layers_[i]->Prepare(); | 
|  | 454 | } | 
|  | 455 |  | 
|  | 456 | // Now that we have taken in a frame from the application, we have a chance | 
|  | 457 | // to drop the frame before passing the frame along to HWC. | 
|  | 458 | // If the display driver has become backed up, we detect it here and then | 
|  | 459 | // react by skipping this frame to catch up latency. | 
|  | 460 | while (!retire_fence_fds_.empty() && | 
|  | 461 | (!retire_fence_fds_.front() || | 
|  | 462 | sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) { | 
|  | 463 | // There are only 2 fences in here, no performance problem to shift the | 
|  | 464 | // array of ints. | 
|  | 465 | retire_fence_fds_.erase(retire_fence_fds_.begin()); | 
|  | 466 | } | 
|  | 467 |  | 
|  | 468 | const bool is_frame_pending = IsFramePendingInDriver(); | 
|  | 469 | const bool is_fence_pending = | 
|  | 470 | retire_fence_fds_.size() > kAllowedPendingFenceCount; | 
|  | 471 |  | 
|  | 472 | if (is_fence_pending || is_frame_pending) { | 
|  | 473 | ATRACE_INT("frame_skip_count", ++frame_skip_count_); | 
|  | 474 |  | 
|  | 475 | ALOGW_IF(is_frame_pending, "Warning: frame already queued, dropping frame"); | 
|  | 476 | ALOGW_IF(is_fence_pending, | 
|  | 477 | "Warning: dropping a frame to catch up with HWC (pending = %zd)", | 
|  | 478 | retire_fence_fds_.size()); | 
|  | 479 |  | 
|  | 480 | for (size_t i = 0; i < active_layer_count_; i++) { | 
|  | 481 | layers_[i]->Drop(); | 
|  | 482 | } | 
|  | 483 | return; | 
|  | 484 | } else { | 
|  | 485 | // Make the transition more obvious in systrace when the frame skip happens | 
|  | 486 | // above. | 
|  | 487 | ATRACE_INT("frame_skip_count", 0); | 
|  | 488 | } | 
|  | 489 |  | 
|  | 490 | #if TRACE | 
|  | 491 | for (size_t i = 0; i < active_layer_count_; i++) | 
|  | 492 | ALOGI("HardwareComposer::PostLayers: dl[%zu] ctype=0x%08x", i, | 
|  | 493 | layers_[i]->GetCompositionType()); | 
|  | 494 | #endif | 
|  | 495 |  | 
|  | 496 | int32_t ret = HWC2_ERROR_NONE; | 
|  | 497 |  | 
|  | 498 | std::vector<Hwc2::IComposerClient::Rect> full_region(1); | 
|  | 499 | full_region[0].left = 0; | 
|  | 500 | full_region[0].top = 0; | 
|  | 501 | full_region[0].right = framebuffer_target_->width(); | 
|  | 502 | full_region[0].bottom = framebuffer_target_->height(); | 
|  | 503 |  | 
|  | 504 | ALOGE_IF(ret, "Error setting client target : %d", ret); | 
|  | 505 |  | 
|  | 506 | ret = Validate(HWC_DISPLAY_PRIMARY); | 
|  | 507 | if (ret) { | 
|  | 508 | ALOGE("HardwareComposer::Validate failed; ret=%d", ret); | 
|  | 509 | return; | 
|  | 510 | } | 
|  | 511 |  | 
|  | 512 | ret = Present(HWC_DISPLAY_PRIMARY); | 
|  | 513 | if (ret) { | 
|  | 514 | ALOGE("HardwareComposer::Present failed; ret=%d", ret); | 
|  | 515 | return; | 
|  | 516 | } | 
|  | 517 |  | 
|  | 518 | std::vector<Hwc2::Layer> out_layers; | 
|  | 519 | std::vector<int> out_fences; | 
|  | 520 | ret = (int32_t)hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers, | 
|  | 521 | &out_fences); | 
|  | 522 | uint32_t num_elements = out_layers.size(); | 
|  | 523 |  | 
|  | 524 | ALOGE_IF(ret, "HardwareComposer: GetReleaseFences failed; ret=%d", ret); | 
|  | 525 |  | 
|  | 526 | // Perform post-frame bookkeeping. Unused layers are a no-op. | 
|  | 527 | for (size_t i = 0; i < num_elements; ++i) { | 
|  | 528 | for (size_t j = 0; j < active_layer_count_; ++j) { | 
|  | 529 | if (layers_[j]->GetLayerHandle() == out_layers[i]) { | 
|  | 530 | layers_[j]->Finish(out_fences[i]); | 
|  | 531 | } | 
|  | 532 | } | 
|  | 533 | } | 
|  | 534 | } | 
|  | 535 |  | 
|  | 536 | // TODO(skiazyk): This is a work-around for the fact that we currently do not | 
|  | 537 | // handle the case when new surfaces are introduced when displayd is not | 
|  | 538 | // in an active state. A proper-solution will require re-structuring | 
|  | 539 | // displayd a little, but hopefully this is sufficient for now. | 
|  | 540 | // For example, could this be handled in |UpdateLayerSettings| instead? | 
|  | 541 | void HardwareComposer::UpdateDisplayState() { | 
|  | 542 | const bool has_display_surfaces = display_surfaces_.size() > 0; | 
|  | 543 |  | 
|  | 544 | if (has_display_surfaces) { | 
| Alex Vakulenko | a8a9278 | 2017-01-27 14:41:57 -0800 | [diff] [blame] | 545 | EnableVsync(true); | 
|  | 546 | } | 
| Jiwen 'Steve' Cai | 105036f | 2017-02-07 16:39:38 -0800 | [diff] [blame] | 547 |  | 
| Alex Vakulenko | a8a9278 | 2017-01-27 14:41:57 -0800 | [diff] [blame] | 548 | // TODO(skiazyk): We need to do something about accessing this directly, | 
|  | 549 | // supposedly there is a backlight service on the way. | 
|  | 550 | SetBacklightBrightness(255); | 
|  | 551 |  | 
| Alex Vakulenko | a8a9278 | 2017-01-27 14:41:57 -0800 | [diff] [blame] | 552 | // Trigger target-specific performance mode change. | 
| Jiwen 'Steve' Cai | 105036f | 2017-02-07 16:39:38 -0800 | [diff] [blame] | 553 | property_set(kDvrPerformanceProperty, has_display_surfaces ? "performance" : "idle"); | 
| Alex Vakulenko | a8a9278 | 2017-01-27 14:41:57 -0800 | [diff] [blame] | 554 | } | 
|  | 555 |  | 
|  | 556 | int HardwareComposer::SetDisplaySurfaces( | 
|  | 557 | std::vector<std::shared_ptr<DisplaySurface>> surfaces) { | 
|  | 558 | std::lock_guard<std::mutex> autolock(layer_mutex_); | 
|  | 559 |  | 
|  | 560 | ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd", | 
|  | 561 | surfaces.size()); | 
|  | 562 |  | 
|  | 563 | // Figure out whether we need to update hardware layers. If this surface | 
|  | 564 | // change does not add or remove hardware layers we can avoid display hiccups | 
|  | 565 | // by gracefully updating only the GPU compositor layers. | 
|  | 566 | // hardware_layers_need_update_ is reset to false by the Post thread. | 
|  | 567 | int old_gpu_layer_count = 0; | 
|  | 568 | int new_gpu_layer_count = 0; | 
|  | 569 | // Look for new hardware layers and count new GPU layers. | 
|  | 570 | for (const auto& surface : surfaces) { | 
|  | 571 | if (!(surface->flags() & | 
|  | 572 | DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION)) | 
|  | 573 | ++new_gpu_layer_count; | 
|  | 574 | else if (std::find(display_surfaces_.begin(), display_surfaces_.end(), | 
|  | 575 | surface) == display_surfaces_.end()) | 
|  | 576 | // This is a new hardware layer, we need to update. | 
|  | 577 | hardware_layers_need_update_ = true; | 
|  | 578 | } | 
|  | 579 | // Look for deleted hardware layers or compositor layers. | 
|  | 580 | for (const auto& surface : display_surfaces_) { | 
|  | 581 | if (!(surface->flags() & | 
|  | 582 | DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION)) | 
|  | 583 | ++old_gpu_layer_count; | 
|  | 584 | else if (std::find(surfaces.begin(), surfaces.end(), surface) == | 
|  | 585 | surfaces.end()) | 
|  | 586 | // This is a deleted hardware layer, we need to update. | 
|  | 587 | hardware_layers_need_update_ = true; | 
|  | 588 | } | 
|  | 589 | // Check for compositor hardware layer transition. | 
|  | 590 | if ((!old_gpu_layer_count && new_gpu_layer_count) || | 
|  | 591 | (old_gpu_layer_count && !new_gpu_layer_count)) | 
|  | 592 | hardware_layers_need_update_ = true; | 
|  | 593 |  | 
|  | 594 | display_surfaces_ = std::move(surfaces); | 
|  | 595 | display_surfaces_updated_ = true; | 
|  | 596 |  | 
|  | 597 | // Set the chosen layer order for all surfaces. | 
|  | 598 | for (size_t i = 0; i < display_surfaces_.size(); ++i) { | 
|  | 599 | display_surfaces_[i]->SetLayerOrder(static_cast<int>(i)); | 
|  | 600 | } | 
|  | 601 |  | 
|  | 602 | // TODO(skiazyk): fix this so that it is handled seamlessly with dormant/non- | 
|  | 603 | // dormant state. | 
|  | 604 | if (!IsSuspended()) { | 
|  | 605 | UpdateDisplayState(); | 
|  | 606 | } | 
|  | 607 |  | 
|  | 608 | return 0; | 
|  | 609 | } | 
|  | 610 |  | 
|  | 611 | // Reads the value of the display driver wait_pingpong state. Returns 0 or 1 | 
|  | 612 | // (the value of the state) on success or a negative error otherwise. | 
|  | 613 | // TODO(eieio): This is pretty driver specific, this should be moved to a | 
|  | 614 | // separate class eventually. | 
|  | 615 | int HardwareComposer::ReadWaitPPState() { | 
|  | 616 | // Gracefully handle when the kernel does not support this feature. | 
|  | 617 | if (!primary_display_wait_pp_fd_) | 
|  | 618 | return 0; | 
|  | 619 |  | 
|  | 620 | const int wait_pp_fd = primary_display_wait_pp_fd_.Get(); | 
|  | 621 | int ret, error; | 
|  | 622 |  | 
|  | 623 | ret = lseek(wait_pp_fd, 0, SEEK_SET); | 
|  | 624 | if (ret < 0) { | 
|  | 625 | error = errno; | 
|  | 626 | ALOGE("HardwareComposer::ReadWaitPPState: Failed to seek wait_pp fd: %s", | 
|  | 627 | strerror(error)); | 
|  | 628 | return -error; | 
|  | 629 | } | 
|  | 630 |  | 
|  | 631 | char data = -1; | 
|  | 632 | ret = read(wait_pp_fd, &data, sizeof(data)); | 
|  | 633 | if (ret < 0) { | 
|  | 634 | error = errno; | 
|  | 635 | ALOGE("HardwareComposer::ReadWaitPPState: Failed to read wait_pp state: %s", | 
|  | 636 | strerror(error)); | 
|  | 637 | return -error; | 
|  | 638 | } | 
|  | 639 |  | 
|  | 640 | switch (data) { | 
|  | 641 | case '0': | 
|  | 642 | return 0; | 
|  | 643 | case '1': | 
|  | 644 | return 1; | 
|  | 645 | default: | 
|  | 646 | ALOGE( | 
|  | 647 | "HardwareComposer::ReadWaitPPState: Unexpected value for wait_pp: %d", | 
|  | 648 | data); | 
|  | 649 | return -EINVAL; | 
|  | 650 | } | 
|  | 651 | } | 
|  | 652 |  | 
|  | 653 | // Reads the timestamp of the last vsync from the display driver. | 
|  | 654 | // TODO(eieio): This is pretty driver specific, this should be moved to a | 
|  | 655 | // separate class eventually. | 
|  | 656 | int HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) { | 
|  | 657 | const int event_fd = primary_display_vsync_event_fd_.Get(); | 
|  | 658 | int ret, error; | 
|  | 659 |  | 
|  | 660 | // The driver returns data in the form "VSYNC=<timestamp ns>". | 
|  | 661 | std::array<char, 32> data; | 
|  | 662 | data.fill('\0'); | 
|  | 663 |  | 
|  | 664 | // Seek back to the beginning of the event file. | 
|  | 665 | ret = lseek(event_fd, 0, SEEK_SET); | 
|  | 666 | if (ret < 0) { | 
|  | 667 | error = errno; | 
|  | 668 | ALOGE( | 
|  | 669 | "HardwareComposer::ReadVSyncTimestamp: Failed to seek vsync event fd: " | 
|  | 670 | "%s", | 
|  | 671 | strerror(error)); | 
|  | 672 | return -error; | 
|  | 673 | } | 
|  | 674 |  | 
|  | 675 | // Read the vsync event timestamp. | 
|  | 676 | ret = read(event_fd, data.data(), data.size()); | 
|  | 677 | if (ret < 0) { | 
|  | 678 | error = errno; | 
|  | 679 | ALOGE_IF( | 
|  | 680 | error != EAGAIN, | 
|  | 681 | "HardwareComposer::ReadVSyncTimestamp: Error while reading timestamp: " | 
|  | 682 | "%s", | 
|  | 683 | strerror(error)); | 
|  | 684 | return -error; | 
|  | 685 | } | 
|  | 686 |  | 
|  | 687 | ret = sscanf(data.data(), "VSYNC=%" PRIu64, | 
|  | 688 | reinterpret_cast<uint64_t*>(timestamp)); | 
|  | 689 | if (ret < 0) { | 
|  | 690 | error = errno; | 
|  | 691 | ALOGE( | 
|  | 692 | "HardwareComposer::ReadVSyncTimestamp: Error while parsing timestamp: " | 
|  | 693 | "%s", | 
|  | 694 | strerror(error)); | 
|  | 695 | return -error; | 
|  | 696 | } | 
|  | 697 |  | 
|  | 698 | return 0; | 
|  | 699 | } | 
|  | 700 |  | 
|  | 701 | // Blocks until the next vsync event is signaled by the display driver. | 
|  | 702 | // TODO(eieio): This is pretty driver specific, this should be moved to a | 
|  | 703 | // separate class eventually. | 
|  | 704 | int HardwareComposer::BlockUntilVSync() { | 
|  | 705 | const int event_fd = primary_display_vsync_event_fd_.Get(); | 
|  | 706 | pollfd pfd[2] = { | 
|  | 707 | { | 
|  | 708 | .fd = event_fd, .events = POLLPRI, .revents = 0, | 
|  | 709 | }, | 
|  | 710 | // This extra event fd is to ensure that we can break out of this loop to | 
|  | 711 | // pause the thread even when vsync is disabled, and thus no events on the | 
|  | 712 | // vsync fd are being generated. | 
|  | 713 | { | 
|  | 714 | .fd = terminate_post_thread_event_fd_.Get(), | 
|  | 715 | .events = POLLPRI | POLLIN, | 
|  | 716 | .revents = 0, | 
|  | 717 | }, | 
|  | 718 | }; | 
|  | 719 | int ret, error; | 
|  | 720 | do { | 
|  | 721 | ret = poll(pfd, 2, -1); | 
|  | 722 | error = errno; | 
|  | 723 | ALOGW_IF(ret < 0, | 
|  | 724 | "HardwareComposer::BlockUntilVSync: Error while waiting for vsync " | 
|  | 725 | "event: %s (%d)", | 
|  | 726 | strerror(error), error); | 
|  | 727 | } while (ret < 0 && error == EINTR); | 
|  | 728 |  | 
|  | 729 | return ret < 0 ? -error : 0; | 
|  | 730 | } | 
|  | 731 |  | 
|  | 732 | // Waits for the next vsync and returns the timestamp of the vsync event. If | 
|  | 733 | // vsync already passed since the last call, returns the latest vsync timestamp | 
|  | 734 | // instead of blocking. This method updates the last_vsync_timeout_ in the | 
|  | 735 | // process. | 
|  | 736 | // | 
|  | 737 | // TODO(eieio): This is pretty driver specific, this should be moved to a | 
|  | 738 | // separate class eventually. | 
|  | 739 | int HardwareComposer::WaitForVSync(int64_t* timestamp) { | 
|  | 740 | int error; | 
|  | 741 |  | 
|  | 742 | // Get the current timestamp and decide what to do. | 
|  | 743 | while (true) { | 
|  | 744 | int64_t current_vsync_timestamp; | 
|  | 745 | error = ReadVSyncTimestamp(¤t_vsync_timestamp); | 
|  | 746 | if (error < 0 && error != -EAGAIN) | 
|  | 747 | return error; | 
|  | 748 |  | 
|  | 749 | if (error == -EAGAIN) { | 
|  | 750 | // Vsync was turned off, wait for the next vsync event. | 
|  | 751 | error = BlockUntilVSync(); | 
|  | 752 | if (error < 0) | 
|  | 753 | return error; | 
|  | 754 |  | 
|  | 755 | // If a request to pause the post thread was given, exit immediately | 
|  | 756 | if (IsSuspended()) { | 
|  | 757 | return 0; | 
|  | 758 | } | 
|  | 759 |  | 
|  | 760 | // Try again to get the timestamp for this new vsync interval. | 
|  | 761 | continue; | 
|  | 762 | } | 
|  | 763 |  | 
|  | 764 | // Check that we advanced to a later vsync interval. | 
|  | 765 | if (TimestampGT(current_vsync_timestamp, last_vsync_timestamp_)) { | 
|  | 766 | *timestamp = last_vsync_timestamp_ = current_vsync_timestamp; | 
|  | 767 | return 0; | 
|  | 768 | } | 
|  | 769 |  | 
|  | 770 | // See how close we are to the next expected vsync. If we're within 1ms, | 
|  | 771 | // sleep for 1ms and try again. | 
|  | 772 | const int64_t ns_per_frame = display_metrics_.vsync_period_ns; | 
|  | 773 | const int64_t threshold_ns = 1000000; | 
|  | 774 |  | 
|  | 775 | const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame; | 
|  | 776 | const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs(); | 
|  | 777 |  | 
|  | 778 | if (distance_to_vsync_est > threshold_ns) { | 
|  | 779 | // Wait for vsync event notification. | 
|  | 780 | error = BlockUntilVSync(); | 
|  | 781 | if (error < 0) | 
|  | 782 | return error; | 
|  | 783 |  | 
|  | 784 | // Again, exit immediately if the thread was requested to pause | 
|  | 785 | if (IsSuspended()) { | 
|  | 786 | return 0; | 
|  | 787 | } | 
|  | 788 | } else { | 
|  | 789 | // Sleep for a short time before retrying. | 
|  | 790 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); | 
|  | 791 | } | 
|  | 792 | } | 
|  | 793 | } | 
|  | 794 |  | 
|  | 795 | int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) { | 
|  | 796 | const int timer_fd = vsync_sleep_timer_fd_.Get(); | 
|  | 797 | const itimerspec wakeup_itimerspec = { | 
|  | 798 | .it_interval = {.tv_sec = 0, .tv_nsec = 0}, | 
|  | 799 | .it_value = NsToTimespec(wakeup_timestamp), | 
|  | 800 | }; | 
|  | 801 | int ret = | 
|  | 802 | timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr); | 
|  | 803 | int error = errno; | 
|  | 804 | if (ret < 0) { | 
|  | 805 | ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s", | 
|  | 806 | strerror(error)); | 
|  | 807 | return -error; | 
|  | 808 | } | 
|  | 809 |  | 
|  | 810 | // Wait for the timer by reading the expiration count. | 
|  | 811 | uint64_t expiration_count; | 
|  | 812 | ret = read(timer_fd, &expiration_count, sizeof(expiration_count)); | 
|  | 813 | if (ret < 0) { | 
|  | 814 | ALOGE("HardwareComposer::SleepUntil: Failed to wait for timerfd: %s", | 
|  | 815 | strerror(error)); | 
|  | 816 | return -error; | 
|  | 817 | } | 
|  | 818 |  | 
|  | 819 | return 0; | 
|  | 820 | } | 
|  | 821 |  | 
|  | 822 | void HardwareComposer::PostThread() { | 
|  | 823 | // NOLINTNEXTLINE(runtime/int) | 
|  | 824 | prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("PostThread"), 0, 0, 0); | 
|  | 825 |  | 
|  | 826 | std::unique_lock<std::mutex> thread_lock(thread_pause_mutex_); | 
|  | 827 |  | 
|  | 828 | // Set the scheduler to SCHED_FIFO with high priority. | 
|  | 829 | int error = dvrSetSchedulerClass(0, "graphics:high"); | 
|  | 830 | LOG_ALWAYS_FATAL_IF( | 
|  | 831 | error < 0, | 
|  | 832 | "HardwareComposer::PostThread: Failed to set scheduler class: %s", | 
|  | 833 | strerror(-error)); | 
|  | 834 | error = dvrSetCpuPartition(0, "/system/performance"); | 
|  | 835 | LOG_ALWAYS_FATAL_IF( | 
|  | 836 | error < 0, | 
|  | 837 | "HardwareComposer::PostThread: Failed to set cpu partition: %s", | 
|  | 838 | strerror(-error)); | 
|  | 839 |  | 
|  | 840 | // Force the layers to be setup at least once. | 
|  | 841 | display_surfaces_updated_ = true; | 
|  | 842 |  | 
|  | 843 | // Initialize the GPU compositor. | 
|  | 844 | LOG_ALWAYS_FATAL_IF(!compositor_.Initialize(GetHmdDisplayMetrics()), | 
|  | 845 | "Failed to initialize the compositor"); | 
|  | 846 |  | 
|  | 847 | const int64_t ns_per_frame = display_metrics_.vsync_period_ns; | 
|  | 848 | const int64_t photon_offset_ns = GetPosePredictionTimeOffset(ns_per_frame); | 
|  | 849 |  | 
|  | 850 | // TODO(jbates) Query vblank time from device, when such an API is available. | 
|  | 851 | // This value (6.3%) was measured on A00 in low persistence mode. | 
|  | 852 | int64_t vblank_ns = ns_per_frame * 63 / 1000; | 
|  | 853 | int64_t right_eye_photon_offset_ns = (ns_per_frame - vblank_ns) / 2; | 
|  | 854 |  | 
|  | 855 | // Check property for overriding right eye offset value. | 
|  | 856 | right_eye_photon_offset_ns = | 
|  | 857 | property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns); | 
|  | 858 |  | 
|  | 859 | // The list of surfaces the compositor should attempt to render. This is set | 
|  | 860 | // at the start of each frame. | 
|  | 861 | std::vector<std::shared_ptr<DisplaySurface>> compositor_surfaces; | 
|  | 862 | compositor_surfaces.reserve(2); | 
|  | 863 |  | 
|  | 864 | // Our history of frame times. This is used to get a better estimate of how | 
|  | 865 | // long the next frame will take, to set a schedule for EDS. | 
|  | 866 | FrameTimeHistory frame_time_history; | 
|  | 867 |  | 
|  | 868 | // The backlog is used to allow us to start rendering the next frame before | 
|  | 869 | // the previous frame has finished, and still get an accurate measurement of | 
|  | 870 | // frame duration. | 
|  | 871 | std::vector<FrameTimeMeasurementRecord> frame_time_backlog; | 
|  | 872 | constexpr int kFrameTimeBacklogMax = 2; | 
|  | 873 | frame_time_backlog.reserve(kFrameTimeBacklogMax); | 
|  | 874 |  | 
|  | 875 | // Storage for retrieving fence info. | 
|  | 876 | FenceInfoBuffer fence_info_buffer; | 
|  | 877 |  | 
|  | 878 | while (1) { | 
|  | 879 | ATRACE_NAME("HardwareComposer::PostThread"); | 
|  | 880 |  | 
|  | 881 | while (IsSuspended()) { | 
|  | 882 | ALOGI("HardwareComposer::PostThread: Post thread pause requested."); | 
|  | 883 | thread_pause_semaphore_.wait(thread_lock); | 
|  | 884 | // The layers will need to be updated since they were deleted previously | 
|  | 885 | display_surfaces_updated_ = true; | 
|  | 886 | hardware_layers_need_update_ = true; | 
|  | 887 | } | 
|  | 888 |  | 
|  | 889 | int64_t vsync_timestamp = 0; | 
|  | 890 | { | 
|  | 891 | std::array<char, 128> buf; | 
|  | 892 | snprintf(buf.data(), buf.size(), "wait_vsync|vsync=%d|", | 
|  | 893 | vsync_count_ + 1); | 
|  | 894 | ATRACE_NAME(buf.data()); | 
|  | 895 |  | 
|  | 896 | error = WaitForVSync(&vsync_timestamp); | 
|  | 897 | ALOGE_IF( | 
|  | 898 | error < 0, | 
|  | 899 | "HardwareComposer::PostThread: Failed to wait for vsync event: %s", | 
|  | 900 | strerror(-error)); | 
|  | 901 |  | 
|  | 902 | // Don't bother processing this frame if a pause was requested | 
|  | 903 | if (IsSuspended()) { | 
|  | 904 | continue; | 
|  | 905 | } | 
|  | 906 | } | 
|  | 907 |  | 
|  | 908 | ++vsync_count_; | 
|  | 909 |  | 
|  | 910 | static double last_print_time = -1; | 
|  | 911 | double current_time = GetSystemClockSec(); | 
|  | 912 | if (last_print_time < 0 || current_time - last_print_time > 3) { | 
|  | 913 | last_print_time = current_time; | 
|  | 914 | } | 
|  | 915 |  | 
|  | 916 | if (pose_client_) { | 
|  | 917 | // Signal the pose service with vsync info. | 
|  | 918 | // Display timestamp is in the middle of scanout. | 
|  | 919 | privateDvrPoseNotifyVsync(pose_client_, vsync_count_, | 
|  | 920 | vsync_timestamp + photon_offset_ns, | 
|  | 921 | ns_per_frame, right_eye_photon_offset_ns); | 
|  | 922 | } | 
|  | 923 |  | 
|  | 924 | bool layer_config_changed = UpdateLayerConfig(&compositor_surfaces); | 
|  | 925 |  | 
|  | 926 | if (layer_config_changed) { | 
|  | 927 | frame_time_history.ResetWithSeed( | 
|  | 928 | GuessFrameTime(compositor_surfaces.size())); | 
|  | 929 | frame_time_backlog.clear(); | 
|  | 930 | } else { | 
|  | 931 | UpdateFrameTimeHistory(&frame_time_backlog, kFrameTimeBacklogMax, | 
|  | 932 | &fence_info_buffer, &frame_time_history); | 
|  | 933 | } | 
|  | 934 |  | 
|  | 935 | // Get our current best estimate at how long the next frame will take to | 
|  | 936 | // render, based on how long previous frames took to render. Use this | 
|  | 937 | // estimate to decide when to wake up for EDS. | 
|  | 938 | int64_t frame_time_estimate = | 
|  | 939 | frame_time_history.GetSampleCount() == 0 | 
|  | 940 | ? GuessFrameTime(compositor_surfaces.size()) | 
|  | 941 | : frame_time_history.GetAverage(); | 
|  | 942 | frame_time_estimate = std::max(frame_time_estimate, kFrameTimeEstimateMin); | 
|  | 943 | DebugHudData::data.hwc_latency = frame_time_estimate; | 
|  | 944 |  | 
|  | 945 | // Signal all of the vsync clients. Because absolute time is used for the | 
|  | 946 | // wakeup time below, this can take a little time if necessary. | 
|  | 947 | if (vsync_callback_) | 
|  | 948 | vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp, frame_time_estimate, | 
|  | 949 | vsync_count_); | 
|  | 950 |  | 
|  | 951 | { | 
|  | 952 | // Sleep until async EDS wakeup time. | 
|  | 953 | ATRACE_NAME("sleep"); | 
|  | 954 |  | 
|  | 955 | int64_t display_time_est = vsync_timestamp + ns_per_frame; | 
|  | 956 | int64_t now = GetSystemClockNs(); | 
|  | 957 | int64_t frame_finish_time_est = now + frame_time_estimate; | 
|  | 958 | int64_t sleep_time_ns = display_time_est - now - frame_time_estimate; | 
|  | 959 |  | 
|  | 960 | ATRACE_INT64("sleep_time_ns", sleep_time_ns); | 
|  | 961 | if (frame_finish_time_est - display_time_est >= kFrameSkipThresholdNs) { | 
|  | 962 | ATRACE_INT("frame_skip_count", ++frame_skip_count_); | 
|  | 963 | ALOGE( | 
|  | 964 | "HardwareComposer::PostThread: Missed frame schedule, drop " | 
|  | 965 | "frame. Expected frame miss: %.1fms", | 
|  | 966 | static_cast<double>(frame_finish_time_est - display_time_est) / | 
|  | 967 | 1000000); | 
|  | 968 |  | 
|  | 969 | // There are several reasons we might skip a frame, but one possibility | 
|  | 970 | // is we mispredicted the frame time. Clear out the frame time history. | 
|  | 971 | frame_time_history.ResetWithSeed( | 
|  | 972 | GuessFrameTime(compositor_surfaces.size())); | 
|  | 973 | frame_time_backlog.clear(); | 
|  | 974 | DebugHudData::data.hwc_frame_stats.SkipFrame(); | 
|  | 975 |  | 
|  | 976 | continue; | 
|  | 977 | } else { | 
|  | 978 | // Make the transition more obvious in systrace when the frame skip | 
|  | 979 | // happens above. | 
|  | 980 | ATRACE_INT("frame_skip_count", 0); | 
|  | 981 | } | 
|  | 982 |  | 
|  | 983 | if (sleep_time_ns > 0) { | 
|  | 984 | error = SleepUntil(display_time_est - frame_time_estimate); | 
|  | 985 | ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s", | 
|  | 986 | strerror(-error)); | 
|  | 987 | } | 
|  | 988 | } | 
|  | 989 |  | 
|  | 990 | DebugHudData::data.hwc_frame_stats.AddFrame(); | 
|  | 991 |  | 
|  | 992 | int64_t frame_start_time = GetSystemClockNs(); | 
|  | 993 |  | 
|  | 994 | // Setup the output buffer for the compositor. This needs to happen before | 
|  | 995 | // you draw with the compositor. | 
|  | 996 | if (gpu_layer_ != nullptr) { | 
|  | 997 | gpu_layer_->UpdateDirectBuffer(compositor_.GetBuffer()); | 
|  | 998 | } | 
|  | 999 |  | 
|  | 1000 | // Call PostLayers now before performing the GL code for the compositor to | 
|  | 1001 | // avoid missing the deadline that can cause the lower-level hwc to get | 
|  | 1002 | // permanently backed up. | 
|  | 1003 | PostLayers(layer_config_changed); | 
|  | 1004 |  | 
|  | 1005 | PostCompositorBuffers(compositor_surfaces); | 
|  | 1006 |  | 
|  | 1007 | if (gpu_layer_ != nullptr) { | 
|  | 1008 | // Note, with scanline racing, this draw is timed along with the post | 
|  | 1009 | // layers to finish just in time. | 
|  | 1010 | LocalHandle frame_fence_fd; | 
|  | 1011 | compositor_.DrawFrame(vsync_count_ + 1, &frame_fence_fd); | 
|  | 1012 | if (frame_fence_fd) { | 
|  | 1013 | LOG_ALWAYS_FATAL_IF(frame_time_backlog.size() >= kFrameTimeBacklogMax, | 
|  | 1014 | "Frame time backlog exceeds capacity"); | 
|  | 1015 | frame_time_backlog.push_back( | 
|  | 1016 | {frame_start_time, std::move(frame_fence_fd)}); | 
|  | 1017 | } | 
|  | 1018 | } else if (!layer_config_changed) { | 
|  | 1019 | frame_time_history.AddSample(GetSystemClockNs() - frame_start_time); | 
|  | 1020 | } | 
|  | 1021 |  | 
|  | 1022 | HandlePendingScreenshots(); | 
|  | 1023 | } | 
|  | 1024 |  | 
|  | 1025 | // TODO(skiazyk): Currently the compositor is not fully releasing its EGL | 
|  | 1026 | // context, which seems to prevent the thread from exiting properly. | 
|  | 1027 | // This shouldn't be too hard to address, I just don't have time right now. | 
|  | 1028 | compositor_.Shutdown(); | 
|  | 1029 | } | 
|  | 1030 |  | 
|  | 1031 | bool HardwareComposer::UpdateLayerConfig( | 
|  | 1032 | std::vector<std::shared_ptr<DisplaySurface>>* compositor_surfaces) { | 
|  | 1033 | std::lock_guard<std::mutex> autolock(layer_mutex_); | 
|  | 1034 |  | 
|  | 1035 | if (!display_surfaces_updated_) | 
|  | 1036 | return false; | 
|  | 1037 |  | 
|  | 1038 | display_surfaces_updated_ = false; | 
|  | 1039 | DebugHudData::data.ResetLayers(); | 
|  | 1040 |  | 
|  | 1041 | // Update compositor layers. | 
|  | 1042 | { | 
|  | 1043 | ATRACE_NAME("UpdateLayerConfig_GpuLayers"); | 
|  | 1044 | compositor_.UpdateSurfaces(display_surfaces_); | 
|  | 1045 | compositor_surfaces->clear(); | 
|  | 1046 | for (size_t i = 0; i < display_surfaces_.size(); ++i) { | 
|  | 1047 | const auto& surface = display_surfaces_[i]; | 
|  | 1048 | if (!(surface->flags() & | 
|  | 1049 | DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION)) { | 
|  | 1050 | compositor_surfaces->push_back(surface); | 
|  | 1051 | } | 
|  | 1052 | } | 
|  | 1053 | } | 
|  | 1054 |  | 
|  | 1055 | if (!hardware_layers_need_update_) | 
|  | 1056 | return true; | 
|  | 1057 |  | 
|  | 1058 | // Update hardware layers. | 
|  | 1059 |  | 
|  | 1060 | ATRACE_NAME("UpdateLayerConfig_HwLayers"); | 
|  | 1061 | hardware_layers_need_update_ = false; | 
|  | 1062 |  | 
|  | 1063 | // Update the display layers in a non-destructive fashion. | 
|  | 1064 |  | 
|  | 1065 | // Create a map from surface id to hardware layer | 
|  | 1066 | std::map<int, Layer*> display_surface_layers; | 
|  | 1067 |  | 
|  | 1068 | for (size_t i = 0; i < active_layer_count_; ++i) { | 
|  | 1069 | auto layer = layers_[i]; | 
|  | 1070 | int surface_id = layer->GetSurfaceId(); | 
|  | 1071 |  | 
|  | 1072 | auto found = | 
|  | 1073 | std::find_if(display_surfaces_.begin(), display_surfaces_.end(), | 
|  | 1074 | [surface_id](const auto& surface) { | 
|  | 1075 | return surface->surface_id() == surface_id; | 
|  | 1076 | }); | 
|  | 1077 |  | 
|  | 1078 | if (found != display_surfaces_.end()) { | 
|  | 1079 | display_surface_layers[surface_id] = layer; | 
|  | 1080 | } | 
|  | 1081 | } | 
|  | 1082 |  | 
|  | 1083 | bool has_gpu_layer = std::any_of( | 
|  | 1084 | display_surfaces_.begin(), display_surfaces_.end(), | 
|  | 1085 | [](const auto& surface) { | 
|  | 1086 | return !(surface->flags() & | 
|  | 1087 | DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION); | 
|  | 1088 | }); | 
|  | 1089 |  | 
|  | 1090 | if (!has_gpu_layer) { | 
|  | 1091 | gpu_layer_ = nullptr; | 
|  | 1092 | } | 
|  | 1093 |  | 
|  | 1094 | auto is_layer_active = [&display_surface_layers, has_gpu_layer](auto layer) { | 
|  | 1095 | int surface_id = layer->GetSurfaceId(); | 
|  | 1096 | if (surface_id >= 0) { | 
|  | 1097 | return display_surface_layers.count(surface_id) > 0; | 
|  | 1098 | } else { | 
|  | 1099 | return has_gpu_layer; | 
|  | 1100 | } | 
|  | 1101 | }; | 
|  | 1102 |  | 
|  | 1103 | // Compress the in-use layers to the top of the list | 
|  | 1104 | auto part = std::partition( | 
|  | 1105 | layers_.begin(), layers_.begin() + active_layer_count_, is_layer_active); | 
|  | 1106 |  | 
|  | 1107 | size_t new_active_layer_count = part - layers_.begin(); | 
|  | 1108 |  | 
|  | 1109 | // Clear any unused layers | 
|  | 1110 | for (size_t i = new_active_layer_count; i < active_layer_count_; ++i) { | 
|  | 1111 | layers_[i]->Reset(); | 
|  | 1112 | } | 
|  | 1113 |  | 
|  | 1114 | active_layer_count_ = new_active_layer_count; | 
|  | 1115 |  | 
|  | 1116 | bool gpu_layer_applied = false; | 
|  | 1117 |  | 
|  | 1118 | // Create/update all of the hardware layers | 
|  | 1119 | for (size_t i = 0; i < display_surfaces_.size(); ++i) { | 
|  | 1120 | const auto& surface = display_surfaces_[i]; | 
|  | 1121 | bool is_hw_surface = | 
|  | 1122 | surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION; | 
|  | 1123 | hwc2_blend_mode_t blending = | 
|  | 1124 | i == 0 ? HWC2_BLEND_MODE_NONE : HWC2_BLEND_MODE_COVERAGE; | 
|  | 1125 |  | 
|  | 1126 | DebugHudData::data.SetLayerInfo( | 
|  | 1127 | i, surface->width(), surface->height(), | 
|  | 1128 | !!(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2)); | 
|  | 1129 |  | 
|  | 1130 | if (!is_hw_surface && gpu_layer_applied) { | 
|  | 1131 | continue; | 
|  | 1132 | } | 
|  | 1133 |  | 
|  | 1134 | Layer* target_layer; | 
|  | 1135 | bool existing_layer = false; | 
|  | 1136 |  | 
|  | 1137 | if (is_hw_surface) { | 
|  | 1138 | auto it = display_surface_layers.find(surface->surface_id()); | 
|  | 1139 |  | 
|  | 1140 | if (it != display_surface_layers.end()) { | 
|  | 1141 | target_layer = it->second; | 
|  | 1142 | existing_layer = true; | 
|  | 1143 | } | 
|  | 1144 | } else if (gpu_layer_ != nullptr) { | 
|  | 1145 | target_layer = gpu_layer_; | 
|  | 1146 | existing_layer = true; | 
|  | 1147 | } | 
|  | 1148 |  | 
|  | 1149 | if (!existing_layer) { | 
|  | 1150 | if (active_layer_count_ >= kMaxHardwareLayers) { | 
|  | 1151 | ALOGI("HardwareComposer: More than %d hardware layers requested.", | 
|  | 1152 | kMaxHardwareLayers); | 
|  | 1153 | break; | 
|  | 1154 | } else { | 
|  | 1155 | target_layer = layers_[active_layer_count_]; | 
|  | 1156 | ++active_layer_count_; | 
|  | 1157 | } | 
|  | 1158 |  | 
|  | 1159 | ALOGD_IF(TRACE, | 
|  | 1160 | "HardwareComposer::UpdateLayerConfig: (new) surface_id=%d -> " | 
|  | 1161 | "layer=%zd", | 
|  | 1162 | surface->surface_id(), i); | 
|  | 1163 |  | 
|  | 1164 | if (is_hw_surface) { | 
|  | 1165 | target_layer->Setup(surface, blending, display_transform_, | 
|  | 1166 | HWC2_COMPOSITION_DEVICE, i); | 
|  | 1167 | } else { | 
|  | 1168 | gpu_layer_ = target_layer; | 
|  | 1169 | target_layer->Setup(compositor_.GetBuffer(), blending, | 
|  | 1170 | display_transform_, HWC2_COMPOSITION_DEVICE, i); | 
|  | 1171 | } | 
|  | 1172 | } else { | 
|  | 1173 | ALOGD_IF(TRACE, | 
|  | 1174 | "HardwareComposer::UpdateLayerConfig: (retained) surface_id=%d " | 
|  | 1175 | "-> layer=%zd", | 
|  | 1176 | surface->surface_id(), i); | 
|  | 1177 |  | 
|  | 1178 | target_layer->SetBlending(blending); | 
|  | 1179 | target_layer->SetZOrderIndex(i); | 
|  | 1180 | target_layer->UpdateLayerSettings(); | 
|  | 1181 | } | 
|  | 1182 |  | 
|  | 1183 | gpu_layer_applied = !is_hw_surface; | 
|  | 1184 | } | 
|  | 1185 |  | 
|  | 1186 | ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers", | 
|  | 1187 | active_layer_count_); | 
|  | 1188 |  | 
|  | 1189 | return true; | 
|  | 1190 | } | 
|  | 1191 |  | 
|  | 1192 | void HardwareComposer::PostCompositorBuffers( | 
|  | 1193 | const std::vector<std::shared_ptr<DisplaySurface>>& compositor_surfaces) { | 
|  | 1194 | ATRACE_NAME("PostCompositorBuffers"); | 
|  | 1195 | for (const auto& surface : compositor_surfaces) { | 
|  | 1196 | compositor_.PostBuffer(surface); | 
|  | 1197 | } | 
|  | 1198 | } | 
|  | 1199 |  | 
|  | 1200 | void HardwareComposer::UpdateFrameTimeHistory( | 
|  | 1201 | std::vector<FrameTimeMeasurementRecord>* backlog, int backlog_max, | 
|  | 1202 | FenceInfoBuffer* fence_info_buffer, FrameTimeHistory* history) { | 
|  | 1203 | while (!backlog->empty()) { | 
|  | 1204 | const auto& frame_time_record = backlog->front(); | 
|  | 1205 | int64_t end_time = 0; | 
|  | 1206 | bool frame_finished = CheckFrameFinished(frame_time_record.fence.Get(), | 
|  | 1207 | fence_info_buffer, &end_time); | 
|  | 1208 | if (frame_finished) { | 
|  | 1209 | int64_t frame_duration = end_time - frame_time_record.start_time; | 
|  | 1210 | history->AddSample(frame_duration); | 
|  | 1211 | // Our backlog is tiny (2 elements), so erasing from the front is ok | 
|  | 1212 | backlog->erase(backlog->begin()); | 
|  | 1213 | } else { | 
|  | 1214 | break; | 
|  | 1215 | } | 
|  | 1216 | } | 
|  | 1217 |  | 
|  | 1218 | if (backlog->size() == static_cast<size_t>(backlog_max)) { | 
|  | 1219 | // Yikes, something must've gone wrong if our oldest frame hasn't finished | 
|  | 1220 | // yet. Give up on waiting for it. | 
|  | 1221 | const auto& stale_frame_time_record = backlog->front(); | 
|  | 1222 | int64_t frame_duration = | 
|  | 1223 | GetSystemClockNs() - stale_frame_time_record.start_time; | 
|  | 1224 | backlog->erase(backlog->begin()); | 
|  | 1225 | history->AddSample(frame_duration); | 
|  | 1226 | ALOGW("Frame didn't finish after %.1fms", | 
|  | 1227 | static_cast<double>(frame_duration) / 1000000); | 
|  | 1228 | } | 
|  | 1229 | } | 
|  | 1230 |  | 
|  | 1231 | bool HardwareComposer::CheckFrameFinished(int frame_fence_fd, | 
|  | 1232 | FenceInfoBuffer* fence_info_buffer, | 
|  | 1233 | int64_t* timestamp) { | 
|  | 1234 | int result = -1; | 
|  | 1235 | int sync_result = sync_wait(frame_fence_fd, 0); | 
|  | 1236 | if (sync_result == 0) { | 
|  | 1237 | result = | 
|  | 1238 | GetFenceSignaledTimestamp(frame_fence_fd, fence_info_buffer, timestamp); | 
|  | 1239 | if (result < 0) { | 
|  | 1240 | ALOGE("Failed getting signaled timestamp from fence"); | 
|  | 1241 | } | 
|  | 1242 | } else if (errno != ETIME) { | 
|  | 1243 | ALOGE("sync_wait on frame fence failed"); | 
|  | 1244 | } | 
|  | 1245 | return result >= 0; | 
|  | 1246 | } | 
|  | 1247 |  | 
|  | 1248 | void HardwareComposer::HandlePendingScreenshots() { | 
|  | 1249 | // Take a screenshot of the requested layer, if available. | 
|  | 1250 | // TODO(eieio): Look into using virtual displays to composite the layer stack | 
|  | 1251 | // into a single output buffer that can be returned to the screenshot clients. | 
|  | 1252 | if (active_layer_count_ > 0) { | 
|  | 1253 | if (auto screenshot_service = ScreenshotService::GetInstance()) { | 
|  | 1254 | if (screenshot_service->IsScreenshotRequestPending()) { | 
|  | 1255 | ATRACE_NAME("screenshot"); | 
|  | 1256 | screenshot_service->TakeIfNeeded(layers_, compositor_); | 
|  | 1257 | } | 
|  | 1258 | } else { | 
|  | 1259 | ALOGW( | 
|  | 1260 | "HardwareComposer::HandlePendingScreenshots: Failed to get " | 
|  | 1261 | "screenshot service!"); | 
|  | 1262 | } | 
|  | 1263 | } | 
|  | 1264 | } | 
|  | 1265 |  | 
|  | 1266 | void HardwareComposer::SetVSyncCallback(VSyncCallback callback) { | 
|  | 1267 | vsync_callback_ = callback; | 
|  | 1268 | } | 
|  | 1269 |  | 
|  | 1270 | void HardwareComposer::HwcRefresh(hwc2_callback_data_t /*data*/, | 
|  | 1271 | hwc2_display_t /*display*/) { | 
|  | 1272 | // TODO(eieio): implement invalidate callbacks. | 
|  | 1273 | } | 
|  | 1274 |  | 
|  | 1275 | void HardwareComposer::HwcVSync(hwc2_callback_data_t /*data*/, | 
|  | 1276 | hwc2_display_t /*display*/, | 
|  | 1277 | int64_t /*timestamp*/) { | 
|  | 1278 | ATRACE_NAME(__PRETTY_FUNCTION__); | 
|  | 1279 | // Intentionally empty. HWC may require a callback to be set to enable vsync | 
|  | 1280 | // signals. We bypass this callback thread by monitoring the vsync event | 
|  | 1281 | // directly, but signals still need to be enabled. | 
|  | 1282 | } | 
|  | 1283 |  | 
|  | 1284 | void HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/, | 
|  | 1285 | hwc2_display_t /*display*/, | 
|  | 1286 | hwc2_connection_t /*connected*/) { | 
|  | 1287 | // TODO(eieio): implement display hotplug callbacks. | 
|  | 1288 | } | 
|  | 1289 |  | 
|  | 1290 | void HardwareComposer::SetBacklightBrightness(int brightness) { | 
|  | 1291 | if (backlight_brightness_fd_) { | 
|  | 1292 | std::array<char, 32> text; | 
|  | 1293 | const int length = snprintf(text.data(), text.size(), "%d", brightness); | 
|  | 1294 | write(backlight_brightness_fd_.Get(), text.data(), length); | 
|  | 1295 | } | 
|  | 1296 | } | 
|  | 1297 |  | 
|  | 1298 | Layer::Layer() | 
|  | 1299 | : hwc2_hidl_(nullptr), | 
|  | 1300 | surface_index_(-1), | 
|  | 1301 | hardware_composer_layer_(0), | 
|  | 1302 | display_metrics_(nullptr), | 
|  | 1303 | blending_(HWC2_BLEND_MODE_NONE), | 
|  | 1304 | transform_(HWC_TRANSFORM_NONE), | 
|  | 1305 | composition_type_(HWC2_COMPOSITION_DEVICE), | 
|  | 1306 | surface_rect_functions_applied_(false) {} | 
|  | 1307 |  | 
|  | 1308 | void Layer::Initialize(Hwc2::Composer* hwc2_hidl, HWCDisplayMetrics* metrics) { | 
|  | 1309 | hwc2_hidl_ = hwc2_hidl; | 
|  | 1310 | display_metrics_ = metrics; | 
|  | 1311 | } | 
|  | 1312 |  | 
|  | 1313 | void Layer::Reset() { | 
|  | 1314 | const int ret = acquired_buffer_.Release(std::move(release_fence_)); | 
|  | 1315 | ALOGE_IF(ret < 0, "Layer::Reset: failed to release buffer: %s", | 
|  | 1316 | strerror(-ret)); | 
|  | 1317 |  | 
|  | 1318 | if (hwc2_hidl_ != nullptr && hardware_composer_layer_) { | 
|  | 1319 | hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_); | 
|  | 1320 | hardware_composer_layer_ = 0; | 
|  | 1321 | } | 
|  | 1322 |  | 
|  | 1323 | surface_index_ = static_cast<size_t>(-1); | 
|  | 1324 | blending_ = HWC2_BLEND_MODE_NONE; | 
|  | 1325 | transform_ = HWC_TRANSFORM_NONE; | 
|  | 1326 | composition_type_ = HWC2_COMPOSITION_DEVICE; | 
|  | 1327 | direct_buffer_ = nullptr; | 
|  | 1328 | surface_ = nullptr; | 
|  | 1329 | acquire_fence_fd_.Close(); | 
|  | 1330 | surface_rect_functions_applied_ = false; | 
|  | 1331 | } | 
|  | 1332 |  | 
|  | 1333 | void Layer::Setup(const std::shared_ptr<DisplaySurface>& surface, | 
|  | 1334 | hwc2_blend_mode_t blending, hwc_transform_t transform, | 
|  | 1335 | hwc2_composition_t composition_type, size_t index) { | 
|  | 1336 | Reset(); | 
|  | 1337 | surface_index_ = index; | 
|  | 1338 | surface_ = surface; | 
|  | 1339 | blending_ = blending; | 
|  | 1340 | transform_ = transform; | 
|  | 1341 | composition_type_ = composition_type; | 
|  | 1342 | CommonLayerSetup(); | 
|  | 1343 | } | 
|  | 1344 |  | 
|  | 1345 | void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer, | 
|  | 1346 | hwc2_blend_mode_t blending, hwc_transform_t transform, | 
|  | 1347 | hwc2_composition_t composition_type, size_t z_order) { | 
|  | 1348 | Reset(); | 
|  | 1349 | surface_index_ = z_order; | 
|  | 1350 | direct_buffer_ = buffer; | 
|  | 1351 | blending_ = blending; | 
|  | 1352 | transform_ = transform; | 
|  | 1353 | composition_type_ = composition_type; | 
|  | 1354 | CommonLayerSetup(); | 
|  | 1355 | } | 
|  | 1356 |  | 
|  | 1357 | void Layer::UpdateDirectBuffer(const std::shared_ptr<IonBuffer>& buffer) { | 
|  | 1358 | direct_buffer_ = buffer; | 
|  | 1359 | } | 
|  | 1360 |  | 
|  | 1361 | void Layer::SetBlending(hwc2_blend_mode_t blending) { blending_ = blending; } | 
|  | 1362 |  | 
|  | 1363 | void Layer::SetZOrderIndex(int z_index) { surface_index_ = z_index; } | 
|  | 1364 |  | 
|  | 1365 | IonBuffer* Layer::GetBuffer() { | 
|  | 1366 | if (direct_buffer_) | 
|  | 1367 | return direct_buffer_.get(); | 
|  | 1368 | else if (acquired_buffer_.IsAvailable()) | 
|  | 1369 | return acquired_buffer_.buffer()->buffer(); | 
|  | 1370 | else | 
|  | 1371 | return nullptr; | 
|  | 1372 | } | 
|  | 1373 |  | 
|  | 1374 | void Layer::UpdateLayerSettings() { | 
|  | 1375 | if (!IsLayerSetup()) { | 
|  | 1376 | ALOGE("HardwareComposer: Trying to update layers data on an unused layer."); | 
|  | 1377 | return; | 
|  | 1378 | } | 
|  | 1379 |  | 
|  | 1380 | int32_t ret = HWC2_ERROR_NONE; | 
|  | 1381 |  | 
|  | 1382 | hwc2_display_t display = HWC_DISPLAY_PRIMARY; | 
|  | 1383 |  | 
|  | 1384 | ret = (int32_t)hwc2_hidl_->setLayerCompositionType( | 
|  | 1385 | display, hardware_composer_layer_, | 
|  | 1386 | (Hwc2::IComposerClient::Composition)composition_type_); | 
|  | 1387 | ALOGE_IF(ret, "HardwareComposer: Error setting layer composition type : %d", | 
|  | 1388 | ret); | 
|  | 1389 | // ret = (int32_t) hwc2_hidl_->setLayerTransform(display, | 
|  | 1390 | // hardware_composer_layer_, | 
|  | 1391 | //                                    (Hwc2::IComposerClient::Transform) | 
|  | 1392 | //                                    transform_); | 
|  | 1393 | // ALOGE_IF(ret, "HardwareComposer: Error setting layer transform : %d", ret); | 
|  | 1394 |  | 
|  | 1395 | // ret = hwc2_funcs_->set_layer_blend_mode_fn_( | 
|  | 1396 | //    hardware_composer_device_, display, hardware_composer_layer_, | 
|  | 1397 | //    blending_); | 
|  | 1398 | ret = (int32_t)hwc2_hidl_->setLayerBlendMode( | 
|  | 1399 | display, hardware_composer_layer_, | 
|  | 1400 | (Hwc2::IComposerClient::BlendMode)blending_); | 
|  | 1401 | ALOGE_IF(ret, "HardwareComposer: Error setting layer blend mode : %d", ret); | 
|  | 1402 |  | 
|  | 1403 | Hwc2::IComposerClient::Rect display_frame; | 
|  | 1404 | display_frame.left = 0; | 
|  | 1405 | display_frame.top = 0; | 
|  | 1406 | display_frame.right = display_metrics_->width; | 
|  | 1407 | display_frame.bottom = display_metrics_->height; | 
|  | 1408 | ret = (int32_t)hwc2_hidl_->setLayerDisplayFrame( | 
|  | 1409 | display, hardware_composer_layer_, display_frame); | 
|  | 1410 | ALOGE_IF(ret, "HardwareComposer: Error setting layer display frame : %d", | 
|  | 1411 | ret); | 
|  | 1412 |  | 
|  | 1413 | std::vector<Hwc2::IComposerClient::Rect> visible_region(1); | 
|  | 1414 | visible_region[0] = display_frame; | 
|  | 1415 | ret = (int32_t)hwc2_hidl_->setLayerVisibleRegion( | 
|  | 1416 | display, hardware_composer_layer_, visible_region); | 
|  | 1417 | ALOGE_IF(ret, "HardwareComposer: Error setting layer visible region : %d", | 
|  | 1418 | ret); | 
|  | 1419 |  | 
|  | 1420 | ret = (int32_t)hwc2_hidl_->setLayerPlaneAlpha(display, | 
|  | 1421 | hardware_composer_layer_, 1.0f); | 
|  | 1422 | ALOGE_IF(ret, "HardwareComposer: Error setting layer plane alpha : %d", ret); | 
|  | 1423 |  | 
|  | 1424 | ret = (int32_t)hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, | 
|  | 1425 | surface_index_); | 
|  | 1426 | ALOGE_IF(ret, "HardwareComposer: Error, setting z order index : %d", ret); | 
|  | 1427 | } | 
|  | 1428 |  | 
|  | 1429 | void Layer::CommonLayerSetup() { | 
|  | 1430 | int32_t ret = (int32_t)hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, | 
|  | 1431 | &hardware_composer_layer_); | 
|  | 1432 |  | 
|  | 1433 | ALOGE_IF(ret, | 
|  | 1434 | "HardwareComposer: Failed to create layer on primary display : %d", | 
|  | 1435 | ret); | 
|  | 1436 |  | 
|  | 1437 | UpdateLayerSettings(); | 
|  | 1438 | } | 
|  | 1439 |  | 
|  | 1440 | void Layer::Prepare() { | 
|  | 1441 | int right, bottom; | 
|  | 1442 | buffer_handle_t handle; | 
|  | 1443 |  | 
|  | 1444 | if (surface_) { | 
|  | 1445 | // Only update the acquired buffer when one is either available or this is | 
|  | 1446 | // the first time through. | 
|  | 1447 | if (surface_->IsBufferAvailable()) { | 
|  | 1448 | // If we previously set this to a solid color layer to stall for time, | 
|  | 1449 | // revert it to a device layer. | 
|  | 1450 | if (acquired_buffer_.IsEmpty() && | 
|  | 1451 | composition_type_ != HWC2_COMPOSITION_DEVICE) { | 
|  | 1452 | composition_type_ = HWC2_COMPOSITION_DEVICE; | 
|  | 1453 | hwc2_hidl_->setLayerCompositionType( | 
|  | 1454 | HWC_DISPLAY_PRIMARY, hardware_composer_layer_, | 
|  | 1455 | (Hwc2::IComposerClient::Composition)HWC2_COMPOSITION_DEVICE); | 
|  | 1456 | } | 
|  | 1457 |  | 
|  | 1458 | DebugHudData::data.AddLayerFrame(surface_index_); | 
|  | 1459 | acquired_buffer_.Release(std::move(release_fence_)); | 
|  | 1460 | acquired_buffer_ = surface_->AcquireCurrentBuffer(); | 
|  | 1461 |  | 
|  | 1462 | // Basic latency stopgap for when the application misses a frame: | 
|  | 1463 | // If the application recovers on the 2nd or 3rd (etc) frame after | 
|  | 1464 | // missing, this code will skip a frame to catch up by checking if | 
|  | 1465 | // the next frame is also available. | 
|  | 1466 | if (surface_->IsBufferAvailable()) { | 
|  | 1467 | DebugHudData::data.SkipLayerFrame(surface_index_); | 
|  | 1468 | ATRACE_NAME("DropToCatchUp"); | 
|  | 1469 | ATRACE_ASYNC_END("BufferPost", acquired_buffer_.buffer()->id()); | 
|  | 1470 | acquired_buffer_ = surface_->AcquireCurrentBuffer(); | 
|  | 1471 | } | 
|  | 1472 | ATRACE_ASYNC_END("BufferPost", acquired_buffer_.buffer()->id()); | 
|  | 1473 | } else if (acquired_buffer_.IsEmpty()) { | 
|  | 1474 | // While we are waiting for a buffer, set this to be an empty layer | 
|  | 1475 | if (composition_type_ != HWC2_COMPOSITION_SOLID_COLOR) { | 
|  | 1476 | composition_type_ = HWC2_COMPOSITION_SOLID_COLOR; | 
|  | 1477 | hwc2_hidl_->setLayerCompositionType( | 
|  | 1478 | HWC_DISPLAY_PRIMARY, hardware_composer_layer_, | 
|  | 1479 | (Hwc2::IComposerClient::Composition)HWC2_COMPOSITION_SOLID_COLOR); | 
|  | 1480 |  | 
|  | 1481 | Hwc2::IComposerClient::Color layer_color = { | 
|  | 1482 | 0, 0, 0, 0, | 
|  | 1483 | }; | 
|  | 1484 | hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_, | 
|  | 1485 | layer_color); | 
|  | 1486 | } | 
|  | 1487 | return; | 
|  | 1488 | } | 
|  | 1489 | right = acquired_buffer_.buffer()->width(); | 
|  | 1490 | bottom = acquired_buffer_.buffer()->height(); | 
|  | 1491 | handle = acquired_buffer_.buffer()->native_handle(); | 
|  | 1492 | acquire_fence_fd_.Reset(acquired_buffer_.ClaimAcquireFence().Release()); | 
|  | 1493 | } else { | 
|  | 1494 | right = direct_buffer_->width(); | 
|  | 1495 | bottom = direct_buffer_->height(); | 
|  | 1496 | handle = direct_buffer_->handle(); | 
|  | 1497 | acquire_fence_fd_.Close(); | 
|  | 1498 | } | 
|  | 1499 |  | 
|  | 1500 | int32_t ret = HWC2_ERROR_NONE; | 
|  | 1501 |  | 
|  | 1502 | if (composition_type_ == HWC2_COMPOSITION_DEVICE) { | 
|  | 1503 | ret = (int32_t)hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY, | 
|  | 1504 | hardware_composer_layer_, handle, | 
|  | 1505 | acquire_fence_fd_.Get()); | 
|  | 1506 |  | 
|  | 1507 | ALOGE_IF(ret, "HardwareComposer: Error setting layer buffer : %d", ret); | 
|  | 1508 | } | 
|  | 1509 |  | 
|  | 1510 | if (!surface_rect_functions_applied_) { | 
|  | 1511 | Hwc2::IComposerClient::FRect crop_rect = { | 
|  | 1512 | 0, 0, static_cast<float>(right), static_cast<float>(bottom), | 
|  | 1513 | }; | 
|  | 1514 | hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY, | 
|  | 1515 | hardware_composer_layer_, crop_rect); | 
|  | 1516 |  | 
|  | 1517 | ALOGE_IF(ret, "HardwareComposer: Error setting layer source crop : %d", | 
|  | 1518 | ret); | 
|  | 1519 |  | 
|  | 1520 | // TODO(skiazyk): why is this ifdef'd out. Is if a driver-specific issue where | 
|  | 1521 | // it must/cannot be called? | 
|  | 1522 | #ifdef QCOM_BSP | 
|  | 1523 | hwc_rect_t damage_rect = { | 
|  | 1524 | 0, 0, right, bottom, | 
|  | 1525 | }; | 
|  | 1526 | hwc_region_t damage = { | 
|  | 1527 | 1, &damage_rect, | 
|  | 1528 | }; | 
|  | 1529 | // ret = hwc2_funcs_->set_layer_surface_damage( | 
|  | 1530 | //    hardware_composer_device_, HWC_DISPLAY_PRIMARY, | 
|  | 1531 | //    hardware_composer_layer_, damage); | 
|  | 1532 | // uses a std::vector as the listing | 
|  | 1533 | // hwc2_hidl_->setLayerSurfaceDamage(HWC_DISPLAY_PRIMARY, | 
|  | 1534 | // hardware_composer_layer_, vector here); | 
|  | 1535 |  | 
|  | 1536 | ALOGE_IF(ret, "HardwareComposer: Error settings layer surface damage : %d", | 
|  | 1537 | ret); | 
|  | 1538 | #endif | 
|  | 1539 |  | 
|  | 1540 | surface_rect_functions_applied_ = true; | 
|  | 1541 | } | 
|  | 1542 | } | 
|  | 1543 |  | 
|  | 1544 | void Layer::Finish(int release_fence_fd) { | 
|  | 1545 | release_fence_.Reset(release_fence_fd); | 
|  | 1546 | } | 
|  | 1547 |  | 
|  | 1548 | void Layer::Drop() { acquire_fence_fd_.Close(); } | 
|  | 1549 |  | 
|  | 1550 | }  // namespace dvr | 
|  | 1551 | }  // namespace android |