• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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