1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "hwc.cf_x86" 18 #define HWC_REMOVE_DEPRECATED_VERSIONS 1 19 20 #include "hwcomposer.h" 21 22 #include <errno.h> 23 #include <stdio.h> 24 #include <sys/resource.h> 25 #include <sys/time.h> 26 #include <string> 27 28 #include <log/log.h> 29 30 namespace cvd { 31 32 void* hwc_vsync_thread(void* data) { 33 struct hwc_composer_device_data_t* pdev = 34 (struct hwc_composer_device_data_t*)data; 35 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); 36 37 int64_t base_timestamp = pdev->vsync_base_timestamp; 38 int64_t last_logged = base_timestamp / 1e9; 39 int sent = 0; 40 int last_sent = 0; 41 static const int log_interval = 60; 42 void (*vsync_proc)(const struct hwc_procs*, int, int64_t) = nullptr; 43 bool log_no_procs = true, log_no_vsync = true; 44 while (true) { 45 struct timespec rt; 46 if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) { 47 ALOGE("%s:%d error in vsync thread clock_gettime: %s", __FILE__, __LINE__, 48 strerror(errno)); 49 } 50 int64_t timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec; 51 // Given now's timestamp calculate the time of the next timestamp. 52 timestamp += pdev->vsync_period_ns - 53 (timestamp - base_timestamp) % pdev->vsync_period_ns; 54 55 rt.tv_sec = timestamp / 1e9; 56 rt.tv_nsec = timestamp % static_cast<int32_t>(1e9); 57 int err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &rt, NULL); 58 if (err == -1) { 59 ALOGE("error in vsync thread: %s", strerror(errno)); 60 if (errno == EINTR) { 61 continue; 62 } 63 } 64 65 // The vsync thread is started on device open, it may run before the 66 // registerProcs callback has a chance to be called, so we need to make sure 67 // procs is not NULL before dereferencing it. 68 if (pdev && pdev->procs) { 69 vsync_proc = pdev->procs->vsync; 70 } else if (log_no_procs) { 71 log_no_procs = false; 72 ALOGI("procs is not set yet, unable to deliver vsync event"); 73 } 74 if (vsync_proc) { 75 vsync_proc(const_cast<hwc_procs_t*>(pdev->procs), 0, timestamp); 76 ++sent; 77 } else if (log_no_vsync) { 78 log_no_vsync = false; 79 ALOGE("vsync callback is null (but procs was already set)"); 80 } 81 if (rt.tv_sec - last_logged > log_interval) { 82 ALOGI("Sent %d syncs in %ds", sent - last_sent, log_interval); 83 last_logged = rt.tv_sec; 84 last_sent = sent; 85 } 86 } 87 88 return NULL; 89 } 90 91 } // namespace cvd 92