1 /* 2 * Copyright (C) 2017 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 #include <pthread.h> 18 #include <sys/resource.h> 19 #include <sys/time.h> 20 21 #include <hardware/hwcomposer.h> 22 #include <hardware/hwcomposer_defs.h> 23 #include <log/log.h> 24 25 #include "common/vsoc/lib/screen_region_view.h" 26 #include "guest/hals/gralloc/gralloc_vsoc_priv.h" 27 28 // This file contains just a skeleton hwcomposer, the first step in the 29 // multisided vsoc hwcomposer for cuttlefish. 30 31 using vsoc::screen::ScreenRegionView; 32 33 // TODO(jemoreira): ScreenRegionView may become the HWC region 34 namespace { 35 36 // Ensures that the layer does not include any inconsistencies 37 int SanityCheckLayer(const hwc_layer_1& layer) { 38 // Check displayFrame 39 if (layer.displayFrame.left > layer.displayFrame.right || 40 layer.displayFrame.top > layer.displayFrame.bottom) { 41 ALOGE( 42 "%s: Malformed rectangle (displayFrame): [left = %d, right = %d, top = " 43 "%d, bottom = %d]", 44 __FUNCTION__, layer.displayFrame.left, layer.displayFrame.right, 45 layer.displayFrame.top, layer.displayFrame.bottom); 46 return -EINVAL; 47 } 48 // Check sourceCrop 49 if (layer.sourceCrop.left > layer.sourceCrop.right || 50 layer.sourceCrop.top > layer.sourceCrop.bottom) { 51 ALOGE( 52 "%s: Malformed rectangle (sourceCrop): [left = %d, right = %d, top = " 53 "%d, bottom = %d]", 54 __FUNCTION__, layer.sourceCrop.left, layer.sourceCrop.right, 55 layer.sourceCrop.top, layer.sourceCrop.bottom); 56 return -EINVAL; 57 } 58 const vsoc_buffer_handle_t* p_handle = 59 reinterpret_cast<const vsoc_buffer_handle_t*>(layer.handle); 60 if (!p_handle) { 61 ALOGE("Layer has a NULL buffer handle"); 62 return -EINVAL; 63 } 64 if (layer.sourceCrop.left < 0 || layer.sourceCrop.top < 0 || 65 layer.sourceCrop.right > p_handle->x_res || 66 layer.sourceCrop.bottom > p_handle->y_res) { 67 ALOGE( 68 "%s: Invalid sourceCrop for buffer handle: sourceCrop = [left = %d, " 69 "right = %d, top = %d, bottom = %d], handle = [width = %d, height = " 70 "%d]", 71 __FUNCTION__, layer.sourceCrop.left, layer.sourceCrop.right, 72 layer.sourceCrop.top, layer.sourceCrop.bottom, p_handle->x_res, 73 p_handle->y_res); 74 return -EINVAL; 75 } 76 return 0; 77 } 78 79 struct vsoc_hwc_device { 80 hwc_composer_device_1_t base; 81 const hwc_procs_t* procs; 82 pthread_t vsync_thread; 83 int64_t vsync_base_timestamp; 84 int32_t vsync_period_ns; 85 uint32_t frame_num; 86 }; 87 88 void* vsync_thread(void* arg) { 89 vsoc_hwc_device* pdev = reinterpret_cast<vsoc_hwc_device*>(arg); 90 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); 91 92 int64_t base_timestamp = pdev->vsync_base_timestamp; 93 int64_t last_logged = base_timestamp / 1e9; 94 int sent = 0; 95 int last_sent = 0; 96 static const int log_interval = 60; 97 void (*vsync_proc)(const struct hwc_procs*, int, int64_t) = nullptr; 98 bool log_no_procs = true, log_no_vsync = true; 99 while (true) { 100 struct timespec rt; 101 if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) { 102 ALOGE("%s:%d error in vsync thread clock_gettime: %s", __FILE__, __LINE__, 103 strerror(errno)); 104 } 105 int64_t timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec; 106 // Given now's timestamp calculate the time of the next vsync. 107 timestamp += pdev->vsync_period_ns - 108 (timestamp - base_timestamp) % pdev->vsync_period_ns; 109 110 rt.tv_sec = timestamp / 1e9; 111 rt.tv_nsec = timestamp % static_cast<int32_t>(1e9); 112 int err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &rt, NULL); 113 if (err == -1) { 114 ALOGE("error in vsync thread: %s", strerror(errno)); 115 if (errno == EINTR) { 116 continue; 117 } 118 } 119 120 // The vsync thread is started on device open, it may run before the 121 // registerProcs callback has a chance to be called, so we need to make sure 122 // procs is not NULL before dereferencing it. 123 if (pdev && pdev->procs) { 124 vsync_proc = pdev->procs->vsync; 125 } else if (log_no_procs) { 126 log_no_procs = false; 127 ALOGI("procs is not set yet, unable to deliver vsync event"); 128 } 129 if (vsync_proc) { 130 vsync_proc(const_cast<hwc_procs_t*>(pdev->procs), 0, timestamp); 131 ++sent; 132 } else if (log_no_vsync) { 133 log_no_vsync = false; 134 ALOGE("vsync callback is null (but procs was already set)"); 135 } 136 if (rt.tv_sec - last_logged > log_interval) { 137 ALOGI("Sent %d syncs in %ds", sent - last_sent, log_interval); 138 last_logged = rt.tv_sec; 139 last_sent = sent; 140 } 141 } 142 143 return NULL; 144 } 145 146 int hwc_prepare(struct hwc_composer_device_1* /*dev*/, size_t numDisplays, 147 hwc_display_contents_1_t** displays) { 148 if (!numDisplays || !displays) return 0; 149 hwc_display_contents_1_t* list = displays[HWC_DISPLAY_PRIMARY]; 150 if (!list) return 0; 151 152 for (size_t i = 0; i < list->numHwLayers; i++) { 153 if (list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) { 154 continue; 155 } 156 list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; 157 } 158 159 return 0; 160 } 161 162 int hwc_set(struct hwc_composer_device_1* dev, size_t numDisplays, 163 hwc_display_contents_1_t** displays) { 164 if (!numDisplays || !displays) return 0; 165 hwc_display_contents_1_t* list = displays[HWC_DISPLAY_PRIMARY]; 166 if (!list) return 0; 167 if (!dev) { 168 ALOGE("%s: dev is NULL", __FUNCTION__); 169 return -EINVAL; 170 } 171 172 for (size_t i = 0; i < list->numHwLayers; i++) { 173 if (vsoc_buffer_handle_t::validate(list->hwLayers[i].handle)) { 174 return -EINVAL; 175 } 176 if (list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) { 177 if (SanityCheckLayer(list->hwLayers[i])) { 178 ALOGW("Skipping layer %zu due to failed sanity check", i); 179 continue; 180 } 181 const vsoc_buffer_handle_t* fb_handle = 182 reinterpret_cast<const vsoc_buffer_handle_t*>( 183 list->hwLayers[i].handle); 184 ScreenRegionView::GetInstance()->BroadcastNewFrame( 185 fb_handle->offset); 186 break; 187 } 188 } 189 190 return 0; 191 } 192 193 int hwc_eventControl(struct hwc_composer_device_1* /*dev*/, int disp, int event, 194 int /*enabled*/) { 195 if (event == HWC_EVENT_VSYNC || disp != HWC_DISPLAY_PRIMARY) { 196 return 0; 197 } 198 return -EINVAL; 199 } 200 201 int hwc_blank(struct hwc_composer_device_1* /*dev*/, int disp, int /*blank*/) { 202 if (disp != HWC_DISPLAY_PRIMARY) { 203 return -EINVAL; 204 } 205 return 0; 206 } 207 208 int hwc_query(struct hwc_composer_device_1* dev, int what, int* value) { 209 vsoc_hwc_device* pdev = reinterpret_cast<vsoc_hwc_device*>(dev); 210 switch (what) { 211 case HWC_BACKGROUND_LAYER_SUPPORTED: 212 // we don't support the background layer 213 *value = 0; 214 break; 215 case HWC_VSYNC_PERIOD: 216 *value = pdev->vsync_period_ns; 217 break; 218 case HWC_DISPLAY_TYPES_SUPPORTED: 219 // We only support the primary display 220 *value = HWC_DISPLAY_PRIMARY_BIT; 221 break; 222 default: 223 // unsupported query 224 ALOGE("%s badness unsupported query what=%d", __FUNCTION__, what); 225 return -EINVAL; 226 } 227 return 0; 228 } 229 230 void hwc_registerProcs(struct hwc_composer_device_1* dev, 231 hwc_procs_t const* procs) { 232 reinterpret_cast<vsoc_hwc_device*>(dev)->procs = procs; 233 } 234 235 void hwc_dump(struct hwc_composer_device_1* /*dev*/, char* /*buff*/, 236 int /*buff_len*/) {} 237 238 int hwc_getDisplayConfigs(struct hwc_composer_device_1* /*dev*/, int disp, 239 uint32_t* configs, size_t* numConfigs) { 240 if (*numConfigs == 0) return 0; 241 242 if (disp == HWC_DISPLAY_PRIMARY) { 243 configs[0] = 0; 244 *numConfigs = 1; 245 return 0; 246 } 247 248 return -EINVAL; 249 } 250 251 int32_t vsoc_hwc_attribute(uint32_t attribute) { 252 auto screen_view = ScreenRegionView::GetInstance(); 253 switch (attribute) { 254 case HWC_DISPLAY_VSYNC_PERIOD: 255 return 1000000000 / screen_view->refresh_rate_hz(); 256 case HWC_DISPLAY_WIDTH: 257 return screen_view->x_res(); 258 case HWC_DISPLAY_HEIGHT: 259 return screen_view->y_res(); 260 case HWC_DISPLAY_DPI_X: 261 case HWC_DISPLAY_DPI_Y: 262 // The number of pixels per thousand inches 263 return screen_view->dpi() * 1000; 264 case HWC_DISPLAY_COLOR_TRANSFORM: 265 // TODO(jemoreira): Add the other color transformations 266 return HAL_COLOR_TRANSFORM_IDENTITY; 267 default: 268 ALOGE("unknown display attribute %u", attribute); 269 return -EINVAL; 270 } 271 } 272 273 int hwc_getDisplayAttributes(struct hwc_composer_device_1* /*dev*/, int disp, 274 uint32_t /*config*/, const uint32_t* attributes, 275 int32_t* values) { 276 277 if (disp != HWC_DISPLAY_PRIMARY) { 278 ALOGE("Unknown display type %u", disp); 279 return -EINVAL; 280 } 281 282 for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) { 283 values[i] = vsoc_hwc_attribute(attributes[i]); 284 } 285 286 return 0; 287 } 288 289 int hwc_close(hw_device_t* device) { 290 vsoc_hwc_device* dev = reinterpret_cast<vsoc_hwc_device*>(device); 291 pthread_kill(dev->vsync_thread, SIGTERM); 292 pthread_join(dev->vsync_thread, NULL); 293 delete dev; 294 return 0; 295 } 296 297 int hwc_open(const struct hw_module_t* module, const char* name, 298 struct hw_device_t** device) { 299 ALOGI("Opening vsoc hwcomposer device: %s", __FUNCTION__); 300 if (strcmp(name, HWC_HARDWARE_COMPOSER)) { 301 ALOGE("%s called with bad name %s", __FUNCTION__, name); 302 return -EINVAL; 303 } 304 305 vsoc_hwc_device* dev = new vsoc_hwc_device(); 306 if (!dev) { 307 ALOGE("%s failed to allocate dev", __FUNCTION__); 308 return -ENOMEM; 309 } 310 memset(dev, 0, sizeof(*dev)); 311 312 int refreshRate = 60; 313 dev->vsync_period_ns = 1000000000 / refreshRate; 314 struct timespec rt; 315 if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) { 316 ALOGE("%s:%d error in clock_gettime: %s", __FILE__, __LINE__, 317 strerror(errno)); 318 } 319 dev->vsync_base_timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec; 320 321 dev->base.common.tag = HARDWARE_DEVICE_TAG; 322 dev->base.common.version = HWC_DEVICE_API_VERSION_1_1; 323 dev->base.common.module = const_cast<hw_module_t*>(module); 324 dev->base.common.close = hwc_close; 325 326 dev->base.prepare = hwc_prepare; 327 dev->base.set = hwc_set; 328 dev->base.query = hwc_query; 329 dev->base.registerProcs = hwc_registerProcs; 330 dev->base.dump = hwc_dump; 331 dev->base.blank = hwc_blank; 332 dev->base.eventControl = hwc_eventControl; 333 dev->base.getDisplayConfigs = hwc_getDisplayConfigs; 334 dev->base.getDisplayAttributes = hwc_getDisplayAttributes; 335 336 if (!ScreenRegionView::GetInstance()) { 337 ALOGE("Unable to open screen region (%s)", __FUNCTION__); 338 delete dev; 339 return -1; 340 } 341 342 int ret = pthread_create(&dev->vsync_thread, NULL, vsync_thread, dev); 343 if (ret) { 344 ALOGE("failed to start vsync thread: %s", strerror(ret)); 345 delete dev; 346 } else { 347 *device = &dev->base.common; 348 } 349 350 return -ret; 351 } 352 353 struct hw_module_methods_t hwc_module_methods = {hwc_open}; 354 355 } // namespace 356 357 hwc_module_t HAL_MODULE_INFO_SYM = {{HARDWARE_MODULE_TAG, 358 HWC_MODULE_API_VERSION_0_1, 359 HARDWARE_HAL_API_VERSION, 360 HWC_HARDWARE_MODULE_ID, 361 "Cuttlefish hwcomposer module", 362 "Google", 363 &hwc_module_methods, 364 NULL, 365 {0}}}; 366