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