2 * Copyright (C) 2012 Intel Corporation. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <hardware/hardware.h>
18 #include <hardware/hwcomposer.h>
19 #include <hardware/gralloc.h>
21 #include <gralloc_drm.h>
22 #include <gralloc_drm_priv.h>
23 #include <gralloc_drm_handle.h>
28 #include <cutils/log.h>
29 #include <cutils/atomic.h>
31 #include <hardware/hwcomposer.h>
35 #define LOG_TAG "hwcomposer"
37 #include <Condition.h>
40 #include <StrongPointer.h>
42 #define SEC_TO_NANOSEC (1000 * 1000 * 1000)
44 static int hwc_device_open(const struct hw_module_t* module, const char* name,
45 struct hw_device_t** device);
47 static struct hw_module_methods_t hwc_module_methods = {
51 hwc_module_t HAL_MODULE_INFO_SYM = {
53 tag: HARDWARE_MODULE_TAG,
56 id: HWC_HARDWARE_MODULE_ID,
57 name: "Intel hwcomposer module",
59 methods: &hwc_module_methods,
68 * To provide refresh timestamps to the surface flinger, using the
69 * same fake mechanism as SF uses on its own, and this is because one
70 * cannot start using hwc until it provides certain mandatory things - the
71 * refresh time stamps being one of them.
73 class vsync_worker : public android::Thread {
75 vsync_worker(struct hwc_context_t& hwc);
76 void set_enabled(bool enabled);
78 virtual void onFirstRef();
79 virtual bool threadLoop();
80 void wait_until_enabled();
82 struct hwc_context_t& dev;
83 mutable android::Mutex lock;
84 android::Condition condition;
86 mutable int64_t next_fake_vsync;
87 int64_t refresh_period;
90 struct hwc_context_t {
91 hwc_composer_device_1 device;
92 struct drm_module_t *gralloc_module;
94 android::sp<vsync_worker> vsync_thread;
97 static void hwc_register_procs(hwc_composer_device_1 *dev,
98 hwc_procs_t const* procs)
100 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
101 ctx->procs = (hwc_procs_t *) procs;
104 static int hwc_event_control(hwc_composer_device_1 *dev, int disp, int event,
107 hwc_context_t* ctx = (hwc_context_t*)dev;
110 * The API restricts 'enabled' as having boolean values only. Also for
111 * now there can be only one fixed display having identifier zero.
113 if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1) || disp)
116 if (ctx->vsync_thread != NULL)
117 ctx->vsync_thread->set_enabled(enabled);
122 static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
123 hwc_display_contents_1_t** displays)
125 struct hwc_context_t* ctx = (struct hwc_context_t *) &dev->common;
127 // SurfaceFlinger wants to handle the complete composition
128 if (!displays[0]->hwLayers || displays[0]->numHwLayers == 0)
131 int topmost = displays[0]->numHwLayers;
132 if (displays[0]->numHwLayers > 0)
135 if (displays[0]->hwLayers->flags & HWC_GEOMETRY_CHANGED) {
136 for (int i=topmost; i>=0; i--) {
137 displays[0]->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
144 static int hwc_set(hwc_composer_device_1 *dev,
145 size_t numDisplays, hwc_display_contents_1_t** displays)
147 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
150 // display is turning off
151 if (!displays[0]->dpy)
154 success = eglSwapBuffers((EGLDisplay)displays[0]->dpy,
155 (EGLSurface)displays[0]->sur);
158 return HWC_EGL_ERROR;
163 // toggle display on or off
164 static int hwc_blank(struct hwc_composer_device_1* dev, int disp, int blank)
166 // dummy implementation for now
170 // query number of different configurations available on display
171 static int hwc_get_display_cfgs(struct hwc_composer_device_1* dev, int disp,
172 uint32_t* configs, size_t* numConfigs)
174 // support just one config per display for now
181 // query display attributes for a particular config
182 static int hwc_get_display_attrs(struct hwc_composer_device_1* dev, int disp,
183 uint32_t config, const uint32_t* attributes, int32_t* values)
186 struct hwc_context_t* ctx = (struct hwc_context_t *) &dev->common;
188 gralloc_drm_t *drm = ctx->gralloc_module->drm;
190 // support only 1 display for now
194 while(attributes[attr] != HWC_DISPLAY_NO_ATTRIBUTE) {
196 case HWC_DISPLAY_VSYNC_PERIOD:
197 values[attr] = drm->primary.mode.vrefresh;
199 case HWC_DISPLAY_WIDTH:
200 values[attr] = drm->primary.mode.hdisplay;
202 case HWC_DISPLAY_HEIGHT:
203 values[attr] = drm->primary.mode.vdisplay;
205 case HWC_DISPLAY_DPI_X:
206 values[attr] = drm->primary.xdpi;
208 case HWC_DISPLAY_DPI_Y:
209 values[attr] = drm->primary.ydpi;
217 static int hwc_device_close(struct hw_device_t *dev)
219 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
224 if (ctx->vsync_thread != NULL)
225 ctx->vsync_thread->requestExitAndWait();
230 /*****************************************************************************/
232 static int hwc_device_open(const struct hw_module_t* module, const char* name,
233 struct hw_device_t** device)
235 int status = -EINVAL;
236 if (strcmp(name, HWC_HARDWARE_COMPOSER))
239 struct hwc_context_t *dev;
240 dev = (hwc_context_t*)calloc(1, sizeof(*dev));
242 /* initialize the procs */
243 dev->device.common.tag = HARDWARE_DEVICE_TAG;
244 dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
245 dev->device.common.module = const_cast<hw_module_t*>(module);
246 dev->device.common.close = hwc_device_close;
248 dev->device.prepare = hwc_prepare;
249 dev->device.set = hwc_set;
250 dev->device.blank = hwc_blank;
251 dev->device.getDisplayAttributes = hwc_get_display_attrs;
252 dev->device.getDisplayConfigs = hwc_get_display_cfgs;
253 dev->device.registerProcs = hwc_register_procs;
254 dev->device.eventControl = hwc_event_control;
256 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
257 (const hw_module_t **)&dev->gralloc_module);
259 ALOGE("hwc_device_open failed!\n");
263 *device = &dev->device.common;
265 dev->vsync_thread = new vsync_worker(*dev);
267 ALOGD("Intel hwcomposer module");
272 /* This is needed here as bionic itself is missing the prototype */
273 extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
274 const struct timespec *request, struct timespec *remain);
277 * XXX: this code is temporary and comes from SurfaceFlinger.cpp
278 * so I changed as little as possible since the code will be dropped
279 * anyway, when real functionality will be implemented
281 vsync_worker::vsync_worker(struct hwc_context_t& mydev)
282 : dev(mydev), enabled(false), next_fake_vsync(0)
285 framebuffer_device_t* fbdev;
287 int err = framebuffer_open((const hw_module_t *)dev.gralloc_module, &fbdev);
289 ALOGE("framebuffer_open failed (%s)", strerror(-err));
291 refresh = int64_t(SEC_TO_NANOSEC / fbdev->fps);
294 refresh = int64_t(SEC_TO_NANOSEC / 60.0);
295 ALOGW("getting VSYNC period from thin air: %lld", refresh);
297 ALOGW("getting VSYNC period from fb HAL: %lld", refresh);
299 refresh_period = refresh;
302 void vsync_worker::set_enabled(bool _enabled)
304 android::Mutex::Autolock _l(lock);
305 if (enabled != _enabled) {
311 void vsync_worker::wait_until_enabled()
313 android::Mutex::Autolock _l(lock);
316 condition.wait(lock);
320 void vsync_worker::onFirstRef()
322 run("vsync_thread", android::PRIORITY_URGENT_DISPLAY +
323 android::PRIORITY_MORE_FAVORABLE);
326 bool vsync_worker::threadLoop()
328 wait_until_enabled();
330 const int64_t now = systemTime(CLOCK_MONOTONIC);
331 int64_t next_vsync = next_fake_vsync;
332 int64_t sleep = next_vsync - now;
334 /* we missed, find where the next vsync should be */
335 ALOGV("vsync missed!");
336 sleep = (refresh_period - ((now - next_vsync) % refresh_period));
337 next_vsync = now + sleep;
340 next_fake_vsync = next_vsync + refresh_period;
342 struct timespec spec;
343 spec.tv_sec = next_vsync / SEC_TO_NANOSEC;
344 spec.tv_nsec = next_vsync % SEC_TO_NANOSEC;
348 err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
349 } while (err < 0 && errno == EINTR);
352 dev.procs->vsync(dev.procs, 0, next_vsync);
354 ALOGE("clock_nanosleep failed with error %d ", err);