1/*
2// Copyright (c) 2014 Intel Corporation 
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#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
18
19#include <hardware/hardware.h>
20#include <string.h>
21#include <stdio.h>
22#include <fcntl.h>
23#include <errno.h>
24#include <common/utils/HwcTrace.h>
25#include <Hwcomposer.h>
26#include <utils/Trace.h>
27
28#define GET_HWC_RETURN_X_IF_NULL(X) \
29    CTRACE(); \
30    Hwcomposer *hwc = static_cast<Hwcomposer*>(dev); \
31    do {\
32        if (!hwc) { \
33            ELOGTRACE("invalid HWC device."); \
34            return X; \
35        } \
36    } while (0)
37
38
39#define GET_HWC_RETURN_ERROR_IF_NULL()        GET_HWC_RETURN_X_IF_NULL(-EINVAL)
40#define GET_HWC_RETURN_VOID_IF_NULL()         GET_HWC_RETURN_X_IF_NULL()
41
42
43namespace android {
44namespace intel {
45
46static int hwc_prepare(struct hwc_composer_device_1 *dev,
47                          size_t numDisplays,
48                          hwc_display_contents_1_t** displays)
49{
50    ATRACE_CALL();
51    GET_HWC_RETURN_ERROR_IF_NULL();
52    if (!hwc->prepare(numDisplays, displays)) {
53        ELOGTRACE("failed to prepare");
54        return -EINVAL;
55    }
56    return 0;
57}
58
59static int hwc_set(struct hwc_composer_device_1 *dev,
60                     size_t numDisplays,
61                     hwc_display_contents_1_t **displays)
62{
63    ATRACE_CALL();
64    GET_HWC_RETURN_ERROR_IF_NULL();
65    if (!hwc->commit(numDisplays, displays)) {
66        ELOGTRACE("failed to commit");
67        return -EINVAL;
68    }
69    return 0;
70}
71
72static void hwc_dump(struct hwc_composer_device_1 *dev,
73                       char *buff,
74                       int buff_len)
75{
76    GET_HWC_RETURN_VOID_IF_NULL();
77    hwc->dump(buff, buff_len, 0);
78}
79
80void hwc_registerProcs(struct hwc_composer_device_1 *dev,
81                          hwc_procs_t const *procs)
82{
83    GET_HWC_RETURN_VOID_IF_NULL();
84    hwc->registerProcs(procs);
85}
86
87static int hwc_device_close(struct hw_device_t * /* dev */)
88{
89    CTRACE();
90    Hwcomposer::releaseInstance();
91    return 0;
92}
93
94static int hwc_query(struct hwc_composer_device_1 * /* dev */,
95        int what, int* /* value */)
96{
97    (void) what;
98    ALOGTRACE("what = %d", what);
99    return -EINVAL;
100}
101
102static int hwc_eventControl(struct hwc_composer_device_1 *dev,
103                                int disp,
104                                int event,
105                                int enabled)
106{
107    bool ret;
108    ATRACE_CALL();
109    GET_HWC_RETURN_ERROR_IF_NULL();
110
111    switch (event) {
112    case HWC_EVENT_VSYNC:
113        ret = hwc->vsyncControl(disp, enabled);
114        if (ret == false) {
115            ELOGTRACE("failed to control vsync");
116            return -EINVAL;
117        }
118        break;
119    default:
120        WLOGTRACE("unsupported event %d", event);
121        break;
122    }
123
124    return 0;
125}
126
127static int hwc_blank(hwc_composer_device_1_t *dev, int disp, int blank)
128{
129    ATRACE_CALL();
130    GET_HWC_RETURN_ERROR_IF_NULL();
131    bool ret = hwc->blank(disp, blank);
132    if (ret == false) {
133        ELOGTRACE("failed to blank disp %d, blank %d", disp, blank);
134        return -EINVAL;
135    }
136
137    return 0;
138}
139
140static int hwc_getDisplayConfigs(hwc_composer_device_1_t *dev,
141                                     int disp,
142                                     uint32_t *configs,
143                                     size_t *numConfigs)
144{
145    ATRACE_CALL();
146    GET_HWC_RETURN_ERROR_IF_NULL();
147    bool ret = hwc->getDisplayConfigs(disp, configs, numConfigs);
148    if (ret == false) {
149        WLOGTRACE("failed to get configs of disp %d", disp);
150        return -EINVAL;
151    }
152
153    return 0;
154}
155
156static int hwc_getDisplayAttributes(hwc_composer_device_1_t *dev,
157                                        int disp,
158                                        uint32_t config,
159                                        const uint32_t *attributes,
160                                        int32_t *values)
161{
162    ATRACE_CALL();
163    GET_HWC_RETURN_ERROR_IF_NULL();
164    bool ret = hwc->getDisplayAttributes(disp, config, attributes, values);
165    if (ret == false) {
166        WLOGTRACE("failed to get attributes of disp %d", disp);
167        return -EINVAL;
168    }
169
170    return 0;
171}
172
173static int hwc_compositionComplete(hwc_composer_device_1_t *dev, int disp)
174{
175    ATRACE_CALL();
176    GET_HWC_RETURN_ERROR_IF_NULL();
177    bool ret = hwc->compositionComplete(disp);
178    if (ret == false) {
179        ELOGTRACE("failed for disp %d", disp);
180        return -EINVAL;
181    }
182
183    return 0;
184}
185
186static int hwc_setPowerMode(hwc_composer_device_1_t *dev, int disp, int mode)
187{
188    ATRACE_CALL();
189    GET_HWC_RETURN_ERROR_IF_NULL();
190    bool ret = hwc->setPowerMode(disp, mode);
191    if (ret == false) {
192        WLOGTRACE("failed to set power mode of disp %d", disp);
193        return -EINVAL;
194    }
195
196    return 0;
197}
198
199static int hwc_getActiveConfig(hwc_composer_device_1_t *dev, int disp)
200{
201    ATRACE_CALL();
202    GET_HWC_RETURN_ERROR_IF_NULL();
203    int ret = hwc->getActiveConfig(disp);
204    if (ret == -1) {
205        WLOGTRACE("failed to get active config of disp %d", disp);
206        return -EINVAL;
207    }
208
209    return ret;
210}
211
212static int hwc_setActiveConfig(hwc_composer_device_1_t *dev, int disp, int index)
213{
214    ATRACE_CALL();
215    GET_HWC_RETURN_ERROR_IF_NULL();
216    bool ret = hwc->setActiveConfig(disp, index);
217    if (ret == false) {
218        WLOGTRACE("failed to set active config of disp %d", disp);
219        return -EINVAL;
220    }
221
222    return 0;
223}
224
225static int hwc_setCursorPositionAsync(hwc_composer_device_1_t *dev, int disp, int x, int y)
226{
227    ATRACE_CALL();
228    GET_HWC_RETURN_ERROR_IF_NULL();
229    bool ret = hwc->setCursorPositionAsync(disp, x, y);
230    if (ret == false) {
231        WLOGTRACE("failed to set cursor position of disp %d", disp);
232        return -EINVAL;
233    }
234
235    return 0;
236}
237
238//------------------------------------------------------------------------------
239
240static int hwc_device_open(const struct hw_module_t* module,
241                              const char* name,
242                              struct hw_device_t** device)
243{
244    if (!name) {
245        ELOGTRACE("invalid name.");
246        return -EINVAL;
247    }
248
249    ALOGTRACE("open device %s", name);
250
251    if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0) {
252        ELOGTRACE("try to open unknown HWComposer %s", name);
253        return -EINVAL;
254    }
255
256    Hwcomposer& hwc = Hwcomposer::getInstance();
257    // initialize our state here
258    if (hwc.initialize() == false) {
259        ELOGTRACE("failed to intialize HWComposer");
260        Hwcomposer::releaseInstance();
261        return -EINVAL;
262    }
263
264    // initialize the procs
265    hwc.hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
266    hwc.hwc_composer_device_1_t::common.module =
267        const_cast<hw_module_t*>(module);
268    hwc.hwc_composer_device_1_t::common.close = hwc_device_close;
269
270    hwc.hwc_composer_device_1_t::prepare = hwc_prepare;
271    hwc.hwc_composer_device_1_t::set = hwc_set;
272    hwc.hwc_composer_device_1_t::dump = hwc_dump;
273    hwc.hwc_composer_device_1_t::registerProcs = hwc_registerProcs;
274    hwc.hwc_composer_device_1_t::query = hwc_query;
275
276    hwc.hwc_composer_device_1_t::eventControl = hwc_eventControl;
277    hwc.hwc_composer_device_1_t::getDisplayConfigs = hwc_getDisplayConfigs;
278    hwc.hwc_composer_device_1_t::getDisplayAttributes = hwc_getDisplayAttributes;
279
280    // This is used to hack FBO switch flush issue in SurfaceFlinger.
281    hwc.hwc_composer_device_1_t::reserved_proc[0] = (void*)hwc_compositionComplete;
282    hwc.hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4;
283    hwc.hwc_composer_device_1_t::setPowerMode = hwc_setPowerMode;
284    hwc.hwc_composer_device_1_t::getActiveConfig = hwc_getActiveConfig;
285    hwc.hwc_composer_device_1_t::setActiveConfig = hwc_setActiveConfig;
286    // Todo: add hwc_setCursorPositionAsync after supporting patches
287    hwc.hwc_composer_device_1_t::setCursorPositionAsync = NULL;
288
289    *device = &hwc.hwc_composer_device_1_t::common;
290
291    return 0;
292}
293
294} // namespace intel
295} // namespace android
296
297static struct hw_module_methods_t hwc_module_methods = {
298    open: android::intel::hwc_device_open
299};
300
301hwc_module_t HAL_MODULE_INFO_SYM = {
302    common: {
303        tag: HARDWARE_MODULE_TAG,
304        version_major: 1,
305        version_minor: 4,
306        id: HWC_HARDWARE_MODULE_ID,
307        name: "Intel Hardware Composer",
308        author: "Intel",
309        methods: &hwc_module_methods,
310        dso: 0,
311        reserved: { 0 },
312    }
313};
314