hwc.cpp revision 2e449280f98f003bb5831c274fc07ab722ac1a94
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012, The Linux Foundation. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <fcntl.h>
19#include <errno.h>
20
21#include <cutils/log.h>
22#include <cutils/atomic.h>
23#include <EGL/egl.h>
24
25#include <overlay.h>
26#include <fb_priv.h>
27#include <mdp_version.h>
28#include "hwc_utils.h"
29#include "hwc_video.h"
30#include "external.h"
31#include "hwc_mdpcomp.h"
32
33using namespace qhwc;
34
35static int hwc_device_open(const struct hw_module_t* module,
36                           const char* name,
37                           struct hw_device_t** device);
38
39static struct hw_module_methods_t hwc_module_methods = {
40    open: hwc_device_open
41};
42
43hwc_module_t HAL_MODULE_INFO_SYM = {
44    common: {
45        tag: HARDWARE_MODULE_TAG,
46        version_major: 2,
47        version_minor: 0,
48        id: HWC_HARDWARE_MODULE_ID,
49        name: "Qualcomm Hardware Composer Module",
50        author: "CodeAurora Forum",
51        methods: &hwc_module_methods,
52        dso: 0,
53        reserved: {0},
54    }
55};
56
57/*
58 * Save callback functions registered to HWC
59 */
60static void hwc_registerProcs(struct hwc_composer_device_1* dev,
61                              hwc_procs_t const* procs)
62{
63    hwc_context_t* ctx = (hwc_context_t*)(dev);
64    if(!ctx) {
65        ALOGE("%s: Invalid context", __FUNCTION__);
66        return;
67    }
68    ctx->proc = procs;
69
70    // don't start listening for events until we can do something with them
71    init_uevent_thread(ctx);
72}
73
74//Helper
75static void reset(hwc_context_t *ctx, int numDisplays) {
76    memset(ctx->listStats, 0, sizeof(ctx->listStats));
77    for(int i = 0; i < numDisplays; i++){
78        ctx->listStats[i].yuvIndex = -1;
79    }
80}
81
82static int hwc_prepare_primary(hwc_composer_device_1 *dev,
83        hwc_display_contents_1_t *list) {
84    hwc_context_t* ctx = (hwc_context_t*)(dev);
85    if (LIKELY(list && list->numHwLayers)) {
86        setListStats(ctx, list, HWC_DISPLAY_PRIMARY);
87        if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY)) {
88            ctx->overlayInUse = true;
89        } else if(MDPComp::configure(ctx, list)) {
90            ctx->overlayInUse = true;
91        } else {
92            ctx->overlayInUse = false;
93        }
94    }
95    return 0;
96}
97
98static int hwc_prepare_external(hwc_composer_device_1 *dev,
99        hwc_display_contents_1_t *list) {
100
101    hwc_context_t* ctx = (hwc_context_t*)(dev);
102    if (LIKELY(list && list->numHwLayers)) {
103        setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
104        //Nothing to do for now
105    }
106    return 0;
107}
108
109static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
110                       hwc_display_contents_1_t** displays)
111{
112    int ret = 0;
113    hwc_context_t* ctx = (hwc_context_t*)(dev);
114    ctx->overlayInUse = false;
115
116    reset(ctx, numDisplays);
117
118    //If securing of h/w in progress skip comp using overlay.
119    if(ctx->mSecuring == true) return 0;
120
121    for (uint32_t i = 0; i < numDisplays; i++) {
122        hwc_display_contents_1_t *list = displays[i];
123        switch(i) {
124            case HWC_DISPLAY_PRIMARY:
125                ret = hwc_prepare_primary(dev, list);
126                break;
127            case HWC_DISPLAY_EXTERNAL:
128                ret = hwc_prepare_external(dev, list);
129                break;
130            default:
131                ret = -EINVAL;
132        }
133    }
134    return ret;
135}
136
137static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
138                             int event, int enabled)
139{
140    int ret = 0;
141    hwc_context_t* ctx = (hwc_context_t*)(dev);
142    private_module_t* m = reinterpret_cast<private_module_t*>(
143                ctx->mFbDev->common.module);
144    switch(event) {
145        case HWC_EVENT_VSYNC:
146            if(ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL,
147                    &enabled) < 0) {
148                ALOGE("%s: vsync control failed. Dpy=%d, enabled=%d : %s",
149                        __FUNCTION__, dpy, enabled, strerror(errno));
150                ret = -errno;
151            }
152            break;
153        default:
154            ret = -EINVAL;
155    }
156    return ret;
157}
158
159static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
160{
161    hwc_context_t* ctx = (hwc_context_t*)(dev);
162    private_module_t* m = reinterpret_cast<private_module_t*>(
163        ctx->mFbDev->common.module);
164    int ret = 0;
165    ALOGD("%s: Doing Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
166    switch(dpy) {
167        case HWC_DISPLAY_PRIMARY:
168            if(blank) {
169                ctx->mOverlay->setState(ovutils::OV_CLOSED);
170                ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
171            } else {
172                ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
173            }
174            break;
175        case HWC_DISPLAY_EXTERNAL:
176            if(blank) {
177                //TODO actual
178            } else {
179            }
180            break;
181        default:
182            return -EINVAL;
183    }
184
185    if(ret < 0) {
186        ALOGE("%s: failed. Dpy=%d, blank=%d : %s",
187                __FUNCTION__, dpy, blank, strerror(errno));
188        return ret;
189    }
190    ALOGD("%s: Done Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
191    ctx->dpyAttr[dpy].isActive = !blank;
192    return 0;
193}
194
195static int hwc_query(struct hwc_composer_device_1* dev,
196                     int param, int* value)
197{
198    hwc_context_t* ctx = (hwc_context_t*)(dev);
199    private_module_t* m = reinterpret_cast<private_module_t*>(
200        ctx->mFbDev->common.module);
201    int supported = HWC_DISPLAY_PRIMARY_BIT;
202
203    switch (param) {
204    case HWC_BACKGROUND_LAYER_SUPPORTED:
205        // Not supported for now
206        value[0] = 0;
207        break;
208    case HWC_VSYNC_PERIOD: //Not used for hwc > 1.1
209        value[0] = m->fps;
210        ALOGI("fps: %d", value[0]);
211        break;
212    case HWC_DISPLAY_TYPES_SUPPORTED:
213        //Enable later
214        //if(ctx->mMDP.hasOverlay)
215            //supported |= HWC_DISPLAY_EXTERNAL_BIT;
216        value[0] = supported;
217        break;
218    default:
219        return -EINVAL;
220    }
221    return 0;
222
223}
224
225static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
226    if (LIKELY(list && list->numHwLayers)) {
227        VideoOverlay::draw(ctx, list, HWC_DISPLAY_PRIMARY);
228        MDPComp::draw(ctx, list);
229        hwc_sync(ctx, list, HWC_DISPLAY_PRIMARY);
230        //TODO We dont check for SKIP flag on this layer because we need PAN
231        //always. Last layer is always FB
232        uint32_t last = list->numHwLayers - 1;
233        if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET) {
234            ctx->mFbDev->post(ctx->mFbDev, list->hwLayers[last].handle);
235        }
236    }
237    return 0;
238}
239
240static int hwc_set_external(hwc_context_t *ctx,
241        hwc_display_contents_1_t* list) {
242    if (LIKELY(list && list->numHwLayers)) {
243        hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL);
244        uint32_t last = list->numHwLayers - 1;
245        if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET &&
246            ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive) {
247            //ctx->mExtDisplay->post(list->hwLayers[last].handle);
248        }
249    }
250    return 0;
251}
252
253static int hwc_set(hwc_composer_device_1 *dev,
254                   size_t numDisplays,
255                   hwc_display_contents_1_t** displays)
256{
257    int ret = 0;
258    hwc_context_t* ctx = (hwc_context_t*)(dev);
259    for (uint32_t i = 0; i < numDisplays; i++) {
260        hwc_display_contents_1_t* list = displays[i];
261        switch(i) {
262            case HWC_DISPLAY_PRIMARY:
263                ret = hwc_set_primary(ctx, list);
264            case HWC_DISPLAY_EXTERNAL:
265                ret = hwc_set_external(ctx, list);
266            default:
267                ret = -EINVAL;
268        }
269    }
270    if(!ctx->overlayInUse)
271        ctx->mOverlay->setState(ovutils::OV_CLOSED);
272
273    return ret;
274}
275
276int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
277        uint32_t* configs, size_t* numConfigs) {
278    int ret = 0;
279    //in 1.1 there is no way to choose a config, report as config id # 0
280    //This config is passed to getDisplayAttributes. Ignore for now.
281    if(*numConfigs == 1)
282        *configs = 0;
283    switch(disp) {
284        case HWC_DISPLAY_PRIMARY:
285            ret = 0;
286            break;
287        case HWC_DISPLAY_EXTERNAL:
288            //Hack until hotplug is supported.
289            //This makes framework ignore external display.
290            ret = -1;
291            break;
292    }
293    return ret;
294}
295
296int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
297        uint32_t config, const uint32_t* attributes, int32_t* values) {
298
299    hwc_context_t* ctx = (hwc_context_t*)(dev);
300    //From HWComposer
301    static const uint32_t DISPLAY_ATTRIBUTES[] = {
302        HWC_DISPLAY_VSYNC_PERIOD,
303        HWC_DISPLAY_WIDTH,
304        HWC_DISPLAY_HEIGHT,
305        HWC_DISPLAY_DPI_X,
306        HWC_DISPLAY_DPI_Y,
307        HWC_DISPLAY_NO_ATTRIBUTE,
308    };
309
310    const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
311            sizeof(DISPLAY_ATTRIBUTES)[0]);
312
313    for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
314        switch (attributes[i]) {
315        case HWC_DISPLAY_VSYNC_PERIOD:
316            values[i] = ctx->dpyAttr[disp].vsync_period;
317            break;
318        case HWC_DISPLAY_WIDTH:
319            values[i] = ctx->dpyAttr[disp].xres;
320            ALOGD("%s width = %d",__FUNCTION__, ctx->dpyAttr[disp].xres);
321            break;
322        case HWC_DISPLAY_HEIGHT:
323            values[i] = ctx->dpyAttr[disp].yres;
324            ALOGD("%s height = %d",__FUNCTION__, ctx->dpyAttr[disp].yres);
325            break;
326        case HWC_DISPLAY_DPI_X:
327            values[i] = ctx->dpyAttr[disp].xdpi;
328            break;
329        case HWC_DISPLAY_DPI_Y:
330            values[i] = ctx->dpyAttr[disp].ydpi;
331            break;
332        default:
333            ALOGE("Unknown display attribute %d",
334                    attributes[i]);
335            return -EINVAL;
336        }
337    }
338    return 0;
339}
340
341static int hwc_device_close(struct hw_device_t *dev)
342{
343    if(!dev) {
344        ALOGE("%s: NULL device pointer", __FUNCTION__);
345        return -1;
346    }
347    closeContext((hwc_context_t*)dev);
348    free(dev);
349
350    return 0;
351}
352
353static int hwc_device_open(const struct hw_module_t* module, const char* name,
354                           struct hw_device_t** device)
355{
356    int status = -EINVAL;
357
358    if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
359        struct hwc_context_t *dev;
360        dev = (hwc_context_t*)malloc(sizeof(*dev));
361        memset(dev, 0, sizeof(*dev));
362
363        //Initialize hwc context
364        initContext(dev);
365
366        //Setup HWC methods
367        dev->device.common.tag          = HARDWARE_DEVICE_TAG;
368        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_1;
369        dev->device.common.module       = const_cast<hw_module_t*>(module);
370        dev->device.common.close        = hwc_device_close;
371        dev->device.prepare             = hwc_prepare;
372        dev->device.set                 = hwc_set;
373        dev->device.eventControl        = hwc_eventControl;
374        dev->device.blank               = hwc_blank;
375        dev->device.query               = hwc_query;
376        dev->device.registerProcs       = hwc_registerProcs;
377        dev->device.dump                = NULL;
378        dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;
379        dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
380        *device = &dev->device.common;
381        status = 0;
382    }
383    return status;
384}
385