Home | History | Annotate | Download | only in common
      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