Android-x86
Fork
Donation

  • R/O
  • HTTP
  • SSH
  • HTTPS

device-generic-goldfish: Commit

device/generic/goldfish


Commit MetaInfo

Revisiond4d0af6f3f24fb7e50cf514e486c7c6e953b6a05 (tree)
Time2017-03-17 03:12:57
AuthorJoshua Lang <joshualang@goog...>
CommiterLingfeng Yang

Log Message

Passthrough hwcomposer for emulator devices

Basic hw composer implementation that directs surface flinger to do all
compositing.

Change-Id: I98e39985ae996db74b655cd4f726680f7066b236
(cherry picked from commit 2d87e1074b72acb859e5b37555266d108af748dd)

Change Summary

Incremental Difference

--- /dev/null
+++ b/hwcomposer/Android.mk
@@ -0,0 +1,66 @@
1+#
2+# Copyright 2015 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+LOCAL_PATH:= $(call my-dir)
18+
19+include $(CLEAR_VARS)
20+emulator_hwcomposer_shared_libraries := \
21+ liblog \
22+ libutils \
23+ libcutils \
24+ libEGL \
25+ libutils \
26+ libhardware \
27+ libsync \
28+ libui \
29+
30+emulator_hwcomposer_src_files := \
31+ hwcomposer.cpp
32+
33+emulator_hwcomposer_cflags += \
34+ -DLOG_TAG=\"hwcomposer\"
35+
36+emulator_hwcomposer_c_includes += \
37+ system/core/libsync \
38+ system/core/libsync/include
39+
40+emulator_hwcomposer_relative_path := hw
41+
42+# GOLDFISH BUILD
43+LOCAL_SHARED_LIBRARIES := $(emulator_hwcomposer_shared_libraries)
44+LOCAL_SRC_FILES := $(emulator_hwcomposer_src_files)
45+LOCAL_CFLAGS := $(emulator_hwcomposer_cflags)
46+LOCAL_C_INCLUDES := $(emulator_hwcomposer_c_includes)
47+LOCAL_MODULE_RELATIVE_PATH := $(emulator_hwcomposer_relative_path)
48+
49+LOCAL_MODULE := hwcomposer.goldfish
50+LOCAL_MODULE_TAGS := optional
51+
52+include $(BUILD_SHARED_LIBRARY)
53+
54+# RANCHU BUILD
55+include $(CLEAR_VARS)
56+
57+LOCAL_SHARED_LIBRARIES := $(emulator_hwcomposer_shared_libraries)
58+LOCAL_SRC_FILES := $(emulator_hwcomposer_src_files)
59+LOCAL_CFLAGS := $(emulator_hwcomposer_cflags)
60+LOCAL_C_INCLUDES := $(emulator_hwcomposer_c_includes)
61+LOCAL_MODULE_RELATIVE_PATH := $(emulator_hwcomposer_relative_path)
62+
63+LOCAL_MODULE := hwcomposer.ranchu
64+LOCAL_MODULE_TAGS := optional
65+
66+include $(BUILD_SHARED_LIBRARY)
--- /dev/null
+++ b/hwcomposer/hwcomposer.cpp
@@ -0,0 +1,355 @@
1+/*
2+ * Copyright (C) 2012 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+#include <pthread.h>
17+#include <stdlib.h>
18+#include <sys/time.h>
19+#include <sys/resource.h>
20+
21+#include <cutils/log.h>
22+#include <hardware/hwcomposer.h>
23+#include <sync/sync.h>
24+
25+struct ranchu_hwc_composer_device_1 {
26+ hwc_composer_device_1_t base; // constant after init
27+ const hwc_procs_t *procs; // constant after init
28+ pthread_t vsync_thread; // constant after init
29+ int32_t vsync_period_ns; // constant after init
30+ framebuffer_device_t* fbdev; // constant after init
31+
32+ pthread_mutex_t vsync_lock;
33+ bool vsync_callback_enabled; // protected by this->vsync_lock
34+};
35+
36+static int hwc_prepare(hwc_composer_device_1_t* dev __unused,
37+ size_t numDisplays, hwc_display_contents_1_t** displays) {
38+
39+ if (!numDisplays || !displays) return 0;
40+
41+ hwc_display_contents_1_t* contents = displays[HWC_DISPLAY_PRIMARY];
42+
43+ if (!contents) return 0;
44+
45+ for (size_t i = 0; i < contents->numHwLayers; i++) {
46+ // We do not handle any layers, so set composition type of any non
47+ // HWC_FRAMEBUFFER_TARGET layer to to HWC_FRAMEBUFFER.
48+ if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
49+ continue;
50+ }
51+ contents->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
52+ }
53+ return 0;
54+}
55+
56+static int hwc_set(struct hwc_composer_device_1* dev,size_t numDisplays,
57+ hwc_display_contents_1_t** displays) {
58+ struct ranchu_hwc_composer_device_1* pdev = (struct ranchu_hwc_composer_device_1*)dev;
59+ if (!numDisplays || !displays) {
60+ return 0;
61+ }
62+
63+ hwc_display_contents_1_t* contents = displays[HWC_DISPLAY_PRIMARY];
64+
65+ int retireFenceFd = -1;
66+ int err = 0;
67+ for (size_t layer = 0; layer < contents->numHwLayers; layer++) {
68+ hwc_layer_1_t* fb_layer = &contents->hwLayers[layer];
69+
70+ int releaseFenceFd = -1;
71+ if (fb_layer->acquireFenceFd > 0) {
72+ const int kAcquireWarningMS= 3000;
73+ err = sync_wait(fb_layer->acquireFenceFd, kAcquireWarningMS);
74+ if (err < 0 && errno == ETIME) {
75+ ALOGE("hwcomposer waited on fence %d for %d ms",
76+ fb_layer->acquireFenceFd, kAcquireWarningMS);
77+ }
78+ close(fb_layer->acquireFenceFd);
79+
80+ if (fb_layer->compositionType != HWC_FRAMEBUFFER_TARGET) {
81+ ALOGE("hwcomposer found acquire fence on layer %d which is not an"
82+ "HWC_FRAMEBUFFER_TARGET layer", layer);
83+ }
84+
85+ releaseFenceFd = dup(fb_layer->acquireFenceFd);
86+ fb_layer->acquireFenceFd = -1;
87+ }
88+
89+ if (fb_layer->compositionType != HWC_FRAMEBUFFER_TARGET) {
90+ continue;
91+ }
92+
93+ pdev->fbdev->post(pdev->fbdev, fb_layer->handle);
94+ fb_layer->releaseFenceFd = releaseFenceFd;
95+
96+ if (releaseFenceFd > 0) {
97+ if (retireFenceFd == -1) {
98+ retireFenceFd = dup(releaseFenceFd);
99+ } else {
100+ int mergedFenceFd = sync_merge("hwc_set retireFence",
101+ releaseFenceFd, retireFenceFd);
102+ close(retireFenceFd);
103+ retireFenceFd = mergedFenceFd;
104+ }
105+ }
106+ }
107+
108+ contents->retireFenceFd = retireFenceFd;
109+ return err;
110+}
111+
112+static int hwc_query(struct hwc_composer_device_1* dev, int what, int* value) {
113+ struct ranchu_hwc_composer_device_1* pdev =
114+ (struct ranchu_hwc_composer_device_1*)dev;
115+
116+ switch (what) {
117+ case HWC_BACKGROUND_LAYER_SUPPORTED:
118+ // we do not support the background layer
119+ value[0] = 0;
120+ break;
121+ case HWC_VSYNC_PERIOD:
122+ value[0] = pdev->vsync_period_ns;
123+ break;
124+ default:
125+ // unsupported query
126+ ALOGE("%s badness unsupported query what=%d", __FUNCTION__, what);
127+ return -EINVAL;
128+ }
129+ return 0;
130+}
131+
132+static int hwc_event_control(struct hwc_composer_device_1* dev, int dpy __unused,
133+ int event, int enabled) {
134+ struct ranchu_hwc_composer_device_1* pdev =
135+ (struct ranchu_hwc_composer_device_1*)dev;
136+ int ret = -EINVAL;
137+
138+ // enabled can only be 0 or 1
139+ if (!(enabled & ~1)) {
140+ if (event == HWC_EVENT_VSYNC) {
141+ pthread_mutex_lock(&pdev->vsync_lock);
142+ pdev->vsync_callback_enabled=enabled;
143+ pthread_mutex_unlock(&pdev->vsync_lock);
144+ ret = 0;
145+ }
146+ }
147+ return ret;
148+}
149+
150+static int hwc_blank(struct hwc_composer_device_1* dev __unused, int disp,
151+ int blank __unused) {
152+ if (disp != HWC_DISPLAY_PRIMARY) {
153+ return -EINVAL;
154+ }
155+ return 0;
156+}
157+
158+static void hwc_dump(hwc_composer_device_1* dev __unused, char* buff __unused,
159+ int buff_len __unused) {
160+ // This is run when running dumpsys.
161+ // No-op for now.
162+}
163+
164+
165+static int hwc_get_display_configs(struct hwc_composer_device_1* dev __unused,
166+ int disp, uint32_t* configs, size_t* numConfigs) {
167+ if (*numConfigs == 0) {
168+ return 0;
169+ }
170+
171+ if (disp == HWC_DISPLAY_PRIMARY) {
172+ configs[0] = 0;
173+ *numConfigs = 1;
174+ return 0;
175+ }
176+
177+ return -EINVAL;
178+}
179+
180+
181+static int32_t hwc_attribute(struct ranchu_hwc_composer_device_1* pdev,
182+ const uint32_t attribute) {
183+ switch(attribute) {
184+ case HWC_DISPLAY_VSYNC_PERIOD:
185+ return pdev->vsync_period_ns;
186+ case HWC_DISPLAY_WIDTH:
187+ return pdev->fbdev->width;
188+ case HWC_DISPLAY_HEIGHT:
189+ return pdev->fbdev->height;
190+ case HWC_DISPLAY_DPI_X:
191+ return pdev->fbdev->xdpi*1000;
192+ case HWC_DISPLAY_DPI_Y:
193+ return pdev->fbdev->ydpi*1000;
194+ default:
195+ ALOGE("unknown display attribute %u", attribute);
196+ return -EINVAL;
197+ }
198+}
199+
200+static int hwc_get_display_attributes(struct hwc_composer_device_1* dev __unused,
201+ int disp, uint32_t config __unused,
202+ const uint32_t* attributes, int32_t* values) {
203+
204+ struct ranchu_hwc_composer_device_1* pdev = (struct ranchu_hwc_composer_device_1*)dev;
205+ for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
206+ if (disp == HWC_DISPLAY_PRIMARY) {
207+ values[i] = hwc_attribute(pdev, attributes[i]);
208+ } else {
209+ ALOGE("unknown display type %u", disp);
210+ return -EINVAL;
211+ }
212+ }
213+
214+ return 0;
215+}
216+
217+static int hwc_close(hw_device_t* dev) {
218+ struct ranchu_hwc_composer_device_1* pdev = (struct ranchu_hwc_composer_device_1*)dev;
219+ pthread_kill(pdev->vsync_thread, SIGTERM);
220+ pthread_join(pdev->vsync_thread, NULL);
221+ free(dev);
222+ return 0;
223+}
224+
225+static void* hwc_vsync_thread(void* data) {
226+ struct ranchu_hwc_composer_device_1* pdev = (struct ranchu_hwc_composer_device_1*)data;
227+ setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
228+
229+ struct timespec rt;
230+ if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
231+ ALOGE("%s:%d error in vsync thread clock_gettime: %s",
232+ __FILE__, __LINE__, strerror(errno));
233+ }
234+ const int log_interval = 60;
235+ int64_t last_logged = rt.tv_sec;
236+ int sent = 0;
237+ int last_sent = 0;
238+ bool vsync_enabled = false;
239+ struct timespec wait_time;
240+ wait_time.tv_sec = 0;
241+ wait_time.tv_nsec = pdev->vsync_period_ns;
242+
243+ while (true) {
244+ int err = nanosleep(&wait_time, NULL);
245+ if (err == -1) {
246+ if (errno == EINTR) {
247+ break;
248+ }
249+ ALOGE("error in vsync thread: %s", strerror(errno));
250+ }
251+
252+ pthread_mutex_lock(&pdev->vsync_lock);
253+ vsync_enabled = pdev->vsync_callback_enabled;
254+ pthread_mutex_unlock(&pdev->vsync_lock);
255+
256+ if (!vsync_enabled) {
257+ continue;
258+ }
259+
260+ if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
261+ ALOGE("%s:%d error in vsync thread clock_gettime: %s",
262+ __FILE__, __LINE__, strerror(errno));
263+ }
264+
265+ int64_t timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec;
266+ pdev->procs->vsync(pdev->procs, 0, timestamp);
267+ if (rt.tv_sec - last_logged >= log_interval) {
268+ ALOGD("hw_composer sent %d syncs in %ds", sent - last_sent, rt.tv_sec - last_logged);
269+ last_logged = rt.tv_sec;
270+ last_sent = sent;
271+ }
272+ ++sent;
273+ }
274+
275+ return NULL;
276+}
277+
278+static void hwc_register_procs(struct hwc_composer_device_1* dev,
279+ hwc_procs_t const* procs) {
280+ struct ranchu_hwc_composer_device_1* pdev = (struct ranchu_hwc_composer_device_1*)dev;
281+ pdev->procs = procs;
282+}
283+
284+static int hwc_open(const struct hw_module_t* module, const char* name,
285+ struct hw_device_t** device) {
286+ int ret = 0;
287+
288+ if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
289+ ALOGE("%s called with bad name %s", __FUNCTION__, name);
290+ return -EINVAL;
291+ }
292+
293+ ranchu_hwc_composer_device_1 *pdev = new ranchu_hwc_composer_device_1();
294+ if (!pdev) {
295+ ALOGE("%s failed to allocate dev", __FUNCTION__);
296+ return -ENOMEM;
297+ }
298+
299+ pdev->base.common.tag = HARDWARE_DEVICE_TAG;
300+ pdev->base.common.version = HWC_DEVICE_API_VERSION_1_1;
301+ pdev->base.common.module = const_cast<hw_module_t *>(module);
302+ pdev->base.common.close = hwc_close;
303+
304+ pdev->base.prepare = hwc_prepare;
305+ pdev->base.set = hwc_set;
306+ pdev->base.eventControl = hwc_event_control;
307+ pdev->base.blank = hwc_blank;
308+ pdev->base.query = hwc_query;
309+ pdev->base.registerProcs = hwc_register_procs;
310+ pdev->base.dump = hwc_dump;
311+ pdev->base.getDisplayConfigs = hwc_get_display_configs;
312+ pdev->base.getDisplayAttributes = hwc_get_display_attributes;
313+
314+ pdev->vsync_period_ns = 1000*1000*1000/60; // vsync is 60 hz
315+
316+ hw_module_t const* hw_module;
317+ ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &hw_module);
318+ if (ret != 0) {
319+ ALOGE("ranchu_hw_composer hwc_open %s module not found", GRALLOC_HARDWARE_MODULE_ID);
320+ return ret;
321+ }
322+ ret = framebuffer_open(hw_module, &pdev->fbdev);
323+ if (ret != 0) {
324+ ALOGE("ranchu_hw_composer hwc_open could not open framebuffer");
325+ }
326+
327+ pthread_mutex_init(&pdev->vsync_lock, NULL);
328+ pdev->vsync_callback_enabled = false;
329+
330+ ret = pthread_create (&pdev->vsync_thread, NULL, hwc_vsync_thread, pdev);
331+ if (ret) {
332+ ALOGE("ranchu_hw_composer could not start vsync_thread\n");
333+ }
334+
335+ *device = &pdev->base.common;
336+
337+ return ret;
338+}
339+
340+
341+static struct hw_module_methods_t hwc_module_methods = {
342+ open: hwc_open,
343+};
344+
345+hwc_module_t HAL_MODULE_INFO_SYM = {
346+ common: {
347+ tag: HARDWARE_MODULE_TAG,
348+ module_api_version: HWC_MODULE_API_VERSION_0_1,
349+ hal_api_version: HARDWARE_HAL_API_VERSION,
350+ id: HWC_HARDWARE_MODULE_ID,
351+ name: "Android Emulator hwcomposer module",
352+ author: "The Android Open Source Project",
353+ methods: &hwc_module_methods,
354+ }
355+};
Show on old repository browser