• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

hardware/intel/hwcomposer


Commit MetaInfo

Revisioncd1bb931979e5a0b9b8f267fa2347bd8d9c28a1b (tree)
Zeit2013-05-16 21:19:44
AutorMarius Predut <marius-ionut.predut@inte...>
CommiterMarius Predut

Log Message

Added support in the hwc to provide refresh timestamps to the surface flinger.

It is done using the same fake mechanism as SF uses. This is prefered until the refresh time stamps will be provides.

v4 (topi):

- switched upper-case style to underscores
- remove code parts that should not be part of this patch but future patch
- update SEC_TO_NANOSEC defined directive and use it in all code.
- wrong comments style fix.
- one-line bodies without the brackets,pure whitespace change

v5 (topi/tapani):

- Indentations fix.
- compiler warning separate patch
- include explanation here for 'enabled' and 'disp'
- added VSYNC missed warning.
- typo fix.

v6(topi/tapani):

- 'vsync missed!' message fixed.
- indentation and newline fixed.

Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
Change-Id: I927e62b5c8c53db859bd194b75f1b92028ea0d85
Signed-off-by: Marius Predut <marius-ionut.predut@intel.com>

Ändern Zusammenfassung

Diff

--- a/Android.mk
+++ b/Android.mk
@@ -17,9 +17,9 @@ LOCAL_PATH := $(call my-dir)
1717 include $(CLEAR_VARS)
1818
1919 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
20-LOCAL_SHARED_LIBRARIES := liblog libEGL libhardware
20+LOCAL_SHARED_LIBRARIES := liblog libEGL libhardware libutils libdrm
2121 LOCAL_CFLAGS := -DEGL_EGLEXT_PROTOTYPES
22-LOCAL_C_INCLUDES += bionic hardware/drm_gralloc external/drm external/drm/include/drm
22+LOCAL_C_INCLUDES += frameworks/native/include/utils/ hardware/drm_gralloc external/drm external/drm/include/drm
2323 LOCAL_SRC_FILES := hwcomposer.cpp
2424 LOCAL_MODULE := hwcomposer.$(TARGET_PRODUCT)
2525 LOCAL_MODULE_TAGS := optional
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -34,10 +34,12 @@
3434
3535 #define HWC_REMOVE_DEPRECATED_VERSIONS 1
3636
37-struct hwc_context_t {
38- hwc_composer_device_1 device;
39- struct drm_module_t *gralloc_module;
40-};
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)
4143
4244 static int hwc_device_open(const struct hw_module_t* module, const char* name,
4345 struct hw_device_t** device);
@@ -59,6 +61,62 @@ hwc_module_t HAL_MODULE_INFO_SYM = {
5961 };
6062
6163
64+/**
65+* Fake VSync class.
66+* To provide refresh timestamps to the surface flinger, using the
67+* same fake mechanism as SF uses on its own, and this is because one
68+* cannot start using hwc until it provides certain mandatory things - the
69+* refresh time stamps being one of them.
70+*/
71+class vsync_worker : public android::Thread {
72+public:
73+ vsync_worker(struct hwc_context_t& hwc);
74+ void set_enabled(bool enabled);
75+private:
76+ virtual void onFirstRef();
77+ virtual bool threadLoop();
78+ void wait_until_enabled();
79+private:
80+ struct hwc_context_t& dev;
81+ mutable android::Mutex lock;
82+ android::Condition condition;
83+ bool enabled;
84+ mutable int64_t next_fake_vsync;
85+ int64_t refresh_period;
86+};
87+
88+struct hwc_context_t {
89+ hwc_composer_device_1 device;
90+ struct drm_module_t *gralloc_module;
91+ hwc_procs_t *procs;
92+ android::sp<vsync_worker> vsync_thread;
93+};
94+
95+static void hwc_register_procs(hwc_composer_device_1 *dev,
96+ hwc_procs_t const* procs)
97+{
98+ struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
99+ ctx->procs = (hwc_procs_t *) procs;
100+}
101+
102+static int hwc_event_control(hwc_composer_device_1 *dev, int disp, int event,
103+ int enabled)
104+{
105+ hwc_context_t* ctx = (hwc_context_t*)dev;
106+
107+ /**
108+ * The API restricts 'enabled' as having boolean values only. Also for
109+ * now there can be only one fixed display having identifier zero.
110+ */
111+ if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1) || disp)
112+ return -EINVAL;
113+
114+ if (ctx->vsync_thread != NULL)
115+ ctx->vsync_thread->set_enabled(enabled);
116+
117+ return 0;
118+}
119+
62120 static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
63121 hwc_display_contents_1_t** displays)
64122 {
@@ -161,6 +219,9 @@ static int hwc_device_close(struct hw_device_t *dev)
161219 if (ctx)
162220 free(ctx);
163221
222+ if (ctx->vsync_thread != NULL)
223+ ctx->vsync_thread->requestExitAndWait();
224+
164225 return 0;
165226 }
166227
@@ -178,7 +239,7 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name,
178239
179240 /* initialize the procs */
180241 dev->device.common.tag = HARDWARE_DEVICE_TAG;
181- dev->device.common.version = 0;
242+ dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
182243 dev->device.common.module = const_cast<hw_module_t*>(module);
183244 dev->device.common.close = hwc_device_close;
184245
@@ -187,13 +248,105 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name,
187248 dev->device.blank = hwc_blank;
188249 dev->device.getDisplayAttributes = hwc_get_display_attrs;
189250 dev->device.getDisplayConfigs = hwc_get_display_cfgs;
251+ dev->device.registerProcs = hwc_register_procs;
252+ dev->device.eventControl = hwc_event_control;
190253
191254 *device = &dev->device.common;
192255
193256 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
194257 (const hw_module_t **)&dev->gralloc_module);
195258
259+ dev->vsync_thread = new vsync_worker(*dev);
260+
196261 ALOGD("Intel hwcomposer module");
197262
198263 return 0;
199264 }
265+
266+/* This is needed here as bionic itself is missing the prototype */
267+extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
268+ const struct timespec *request, struct timespec *remain);
269+
270+/**
271+ * XXX: this code is temporary and comes from SurfaceFlinger.cpp
272+ * so I changed as little as possible since the code will be dropped
273+ * anyway, when real functionality will be implemented
274+ */
275+vsync_worker::vsync_worker(struct hwc_context_t& mydev)
276+ : dev(mydev), enabled(false), next_fake_vsync(0)
277+{
278+ int64_t refresh = 0;
279+ framebuffer_device_t* fbdev;
280+
281+ int err = framebuffer_open((const hw_module_t *)dev.gralloc_module, &fbdev);
282+ if (err)
283+ ALOGE("framebuffer_open failed (%s)", strerror(-err));
284+ else
285+ refresh = int64_t(SEC_TO_NANOSEC / fbdev->fps);
286+
287+ if (refresh == 0) {
288+ refresh = int64_t(SEC_TO_NANOSEC / 60.0);
289+ ALOGW("getting VSYNC period from thin air: %lld", refresh);
290+ } else
291+ ALOGW("getting VSYNC period from fb HAL: %lld", refresh);
292+
293+ refresh_period = refresh;
294+}
295+
296+void vsync_worker::set_enabled(bool _enabled)
297+{
298+ android::Mutex::Autolock _l(lock);
299+ if (enabled != _enabled) {
300+ enabled = _enabled;
301+ condition.signal();
302+ }
303+}
304+
305+void vsync_worker::wait_until_enabled()
306+{
307+ android::Mutex::Autolock _l(lock);
308+
309+ while (!enabled) {
310+ condition.wait(lock);
311+ }
312+}
313+
314+void vsync_worker::onFirstRef()
315+{
316+ run("vsync_thread", android::PRIORITY_URGENT_DISPLAY +
317+ android::PRIORITY_MORE_FAVORABLE);
318+}
319+
320+bool vsync_worker::threadLoop()
321+{
322+ wait_until_enabled();
323+
324+ const int64_t now = systemTime(CLOCK_MONOTONIC);
325+ int64_t next_vsync = next_fake_vsync;
326+ int64_t sleep = next_vsync - now;
327+ if (sleep < 0) {
328+ /* we missed, find where the next vsync should be */
329+ ALOGV("vsync missed!");
330+ sleep = (refresh_period - ((now - next_vsync) % refresh_period));
331+ next_vsync = now + sleep;
332+ }
333+
334+ next_fake_vsync = next_vsync + refresh_period;
335+
336+ struct timespec spec;
337+ spec.tv_sec = next_vsync / SEC_TO_NANOSEC;
338+ spec.tv_nsec = next_vsync % SEC_TO_NANOSEC;
339+
340+ int err;
341+ do {
342+ err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
343+ } while (err < 0 && errno == EINTR);
344+
345+ if (err == 0)
346+ dev.procs->vsync(dev.procs, 0, next_vsync);
347+ else
348+ ALOGE("clock_nanosleep failed with error %d ", err);
349+
350+ return true;
351+}
352+