OSDN Git Service

enable multiarch builds
[android-x86/hardware-intel-hwcomposer.git] / hwcomposer.cpp
1 /*
2  * Copyright (C) 2012 Intel Corporation. All rights reserved.
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 <hardware/hardware.h>
18 #include <hardware/hwcomposer.h>
19 #include <hardware/gralloc.h>
20
21 #include <gralloc_drm.h>
22 #include <gralloc_drm_priv.h>
23 #include <gralloc_drm_handle.h>
24
25 #include <fcntl.h>
26 #include <errno.h>
27
28 #include <cutils/log.h>
29 #include <cutils/atomic.h>
30
31 #include <hardware/hwcomposer.h>
32
33 #include <EGL/egl.h>
34
35 #define LOG_TAG "hwcomposer"
36
37 #include <Condition.h>
38 #include <Mutex.h>
39 #include <Thread.h>
40 #include <StrongPointer.h>
41
42 #define SEC_TO_NANOSEC (1000 * 1000 * 1000)
43
44 static int hwc_device_open(const struct hw_module_t* module, const char* name,
45                 struct hw_device_t** device);
46
47 static struct hw_module_methods_t hwc_module_methods = {
48         open: hwc_device_open
49 };
50
51 hwc_module_t HAL_MODULE_INFO_SYM = {
52         common: {
53                 tag: HARDWARE_MODULE_TAG,
54                 version_major: 1,
55                 version_minor: 0,
56                 id: HWC_HARDWARE_MODULE_ID,
57                 name: "Intel hwcomposer module",
58                 author: "Intel",
59                 methods: &hwc_module_methods,
60                 dso: NULL,
61                 {0}
62         }
63 };
64
65
66 /**
67 * Fake VSync class.
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.
72 */
73 class vsync_worker : public android::Thread {
74 public:
75         vsync_worker(struct hwc_context_t& hwc);
76         void set_enabled(bool enabled);
77 private:
78         virtual void onFirstRef();
79         virtual bool threadLoop();
80         void wait_until_enabled();
81 private:
82         struct hwc_context_t& dev;
83         mutable android::Mutex lock;
84         android::Condition condition;
85         bool enabled;
86         mutable int64_t next_fake_vsync;
87         int64_t refresh_period;
88 };
89
90 struct hwc_context_t {
91         hwc_composer_device_1 device;
92         struct drm_module_t *gralloc_module;
93         hwc_procs_t *procs;
94         android::sp<vsync_worker> vsync_thread;
95 };
96
97 static void hwc_register_procs(hwc_composer_device_1 *dev,
98                         hwc_procs_t const* procs)
99 {
100         struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
101         ctx->procs = (hwc_procs_t *) procs;
102 }
103
104 static int hwc_event_control(hwc_composer_device_1 *dev, int disp, int event,
105                                 int enabled)
106 {
107         hwc_context_t* ctx = (hwc_context_t*)dev;
108
109         /**
110          * The API restricts 'enabled' as having boolean values only. Also for
111          * now there can be only one fixed display having identifier zero.
112          */
113         if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1) || disp)
114                 return -EINVAL;
115
116         if (ctx->vsync_thread != NULL)
117                 ctx->vsync_thread->set_enabled(enabled);
118
119         return 0;
120 }
121
122 static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
123         hwc_display_contents_1_t** displays)
124 {
125         struct hwc_context_t* ctx = (struct hwc_context_t *) &dev->common;
126
127         // SurfaceFlinger wants to handle the complete composition
128         if (!displays[0]->hwLayers || displays[0]->numHwLayers == 0)
129                 return 0;
130
131         int topmost = displays[0]->numHwLayers;
132         if (displays[0]->numHwLayers > 0)
133                 topmost--;
134
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;
138                 }
139         }
140         return 0;
141 }
142
143
144 static int hwc_set(hwc_composer_device_1 *dev,
145                 size_t numDisplays, hwc_display_contents_1_t** displays)
146 {
147         struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
148         EGLBoolean success;
149
150         // display is turning off
151         if (!displays[0]->dpy)
152                 return 0;
153
154         success = eglSwapBuffers((EGLDisplay)displays[0]->dpy,
155                 (EGLSurface)displays[0]->sur);
156
157         if (!success)
158                 return HWC_EGL_ERROR;
159
160         return 0;
161 }
162
163 // toggle display on or off
164 static int hwc_blank(struct hwc_composer_device_1* dev, int disp, int blank)
165 {
166         // dummy implementation for now
167         return 0;
168 }
169
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)
173 {
174         // support just one config per display for now
175         *configs = 1;
176         *numConfigs = 1;
177
178         return 0;
179 }
180
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)
184 {
185         int attr = 0;
186         struct hwc_context_t* ctx = (struct hwc_context_t *) &dev->common;
187
188         gralloc_drm_t *drm = ctx->gralloc_module->drm;
189
190         // support only 1 display for now
191         if (disp > 0)
192                 return -EINVAL;
193
194         while(attributes[attr] != HWC_DISPLAY_NO_ATTRIBUTE) {
195                 switch (attr) {
196                         case HWC_DISPLAY_VSYNC_PERIOD:
197                                 values[attr] = drm->primary.mode.vrefresh;
198                                 break;
199                         case HWC_DISPLAY_WIDTH:
200                                 values[attr] = drm->primary.mode.hdisplay;
201                                 break;
202                         case HWC_DISPLAY_HEIGHT:
203                                 values[attr] = drm->primary.mode.vdisplay;
204                                 break;
205                         case HWC_DISPLAY_DPI_X:
206                                 values[attr] = drm->primary.xdpi;
207                                 break;
208                         case HWC_DISPLAY_DPI_Y:
209                                 values[attr] = drm->primary.ydpi;
210                                 break;
211                 }
212                 attr++;
213         }
214         return 0;
215 }
216
217 static int hwc_device_close(struct hw_device_t *dev)
218 {
219         struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
220
221         if (ctx)
222                 free(ctx);
223
224         if (ctx->vsync_thread != NULL)
225                 ctx->vsync_thread->requestExitAndWait();
226
227         return 0;
228 }
229
230 /*****************************************************************************/
231
232 static int hwc_device_open(const struct hw_module_t* module, const char* name,
233                 struct hw_device_t** device)
234 {
235         int status = -EINVAL;
236         if (strcmp(name, HWC_HARDWARE_COMPOSER))
237                 return status;
238
239         struct hwc_context_t *dev;
240         dev = (hwc_context_t*)calloc(1, sizeof(*dev));
241
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;
247
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;
255
256         int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
257                 (const hw_module_t **)&dev->gralloc_module);
258         if (err != 0) {
259                 ALOGE("hwc_device_open failed!\n");
260                 return -errno;
261         }
262
263         *device = &dev->device.common;
264
265         dev->vsync_thread = new vsync_worker(*dev);
266
267         ALOGD("Intel hwcomposer module");
268
269         return 0;
270 }
271
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);
275
276 /**
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
280  */
281 vsync_worker::vsync_worker(struct hwc_context_t& mydev)
282         : dev(mydev), enabled(false), next_fake_vsync(0)
283 {
284         int64_t refresh = 0;
285         framebuffer_device_t*   fbdev;
286
287         int err = framebuffer_open((const hw_module_t *)dev.gralloc_module, &fbdev);
288         if (err)
289                 ALOGE("framebuffer_open failed (%s)", strerror(-err));
290         else
291                 refresh = int64_t(SEC_TO_NANOSEC / fbdev->fps);
292
293         if (refresh == 0) {
294                 refresh = int64_t(SEC_TO_NANOSEC / 60.0);
295                 ALOGW("getting VSYNC period from thin air: %lld", refresh);
296         } else
297                 ALOGW("getting VSYNC period from fb HAL: %lld", refresh);
298
299         refresh_period = refresh;
300 }
301
302 void vsync_worker::set_enabled(bool _enabled)
303 {
304         android::Mutex::Autolock _l(lock);
305         if (enabled != _enabled) {
306                 enabled = _enabled;
307                 condition.signal();
308         }
309 }
310
311 void vsync_worker::wait_until_enabled()
312 {
313         android::Mutex::Autolock _l(lock);
314
315         while (!enabled) {
316                 condition.wait(lock);
317         }
318 }
319
320 void vsync_worker::onFirstRef()
321 {
322         run("vsync_thread", android::PRIORITY_URGENT_DISPLAY +
323                                         android::PRIORITY_MORE_FAVORABLE);
324 }
325
326 bool vsync_worker::threadLoop()
327 {
328         wait_until_enabled();
329
330         const int64_t now = systemTime(CLOCK_MONOTONIC);
331         int64_t next_vsync = next_fake_vsync;
332         int64_t sleep = next_vsync - now;
333         if (sleep < 0) {
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;
338         }
339
340         next_fake_vsync = next_vsync + refresh_period;
341
342         struct timespec spec;
343         spec.tv_sec  = next_vsync / SEC_TO_NANOSEC;
344         spec.tv_nsec = next_vsync % SEC_TO_NANOSEC;
345
346         int err;
347         do {
348                 err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
349         } while (err < 0 && errno == EINTR);
350
351         if (err == 0)
352                 dev.procs->vsync(dev.procs, 0, next_vsync);
353         else
354                 ALOGE("clock_nanosleep failed with error %d ", err);
355
356         return true;
357 }
358