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