hwc.cpp revision 25322c7f78dfeb2c9c441dc0720dba6c639b198c
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_qbuf.h"
30#include "hwc_video.h"
31#include "hwc_uimirror.h"
32#include "hwc_copybit.h"
33#include "external.h"
34#include "hwc_mdpcomp.h"
35#include "hwc_extonly.h"
36
37using namespace qhwc;
38
39static int hwc_device_open(const struct hw_module_t* module,
40                           const char* name,
41                           struct hw_device_t** device);
42
43static struct hw_module_methods_t hwc_module_methods = {
44    open: hwc_device_open
45};
46
47hwc_module_t HAL_MODULE_INFO_SYM = {
48    common: {
49        tag: HARDWARE_MODULE_TAG,
50        version_major: 2,
51        version_minor: 0,
52        id: HWC_HARDWARE_MODULE_ID,
53        name: "Qualcomm Hardware Composer Module",
54        author: "CodeAurora Forum",
55        methods: &hwc_module_methods,
56        dso: 0,
57        reserved: {0},
58    }
59};
60
61/*
62 * Save callback functions registered to HWC
63 */
64static void hwc_registerProcs(struct hwc_composer_device_1* dev,
65                              hwc_procs_t const* procs)
66{
67    hwc_context_t* ctx = (hwc_context_t*)(dev);
68    if(!ctx) {
69        ALOGE("%s: Invalid context", __FUNCTION__);
70        return;
71    }
72    ctx->proc = procs;
73
74    // don't start listening for events until we can do something with them
75    init_uevent_thread(ctx);
76}
77
78//Helper
79static void reset() {
80    //reset for this draw round
81    VideoOverlay::reset();
82    ExtOnly::reset();
83    UIMirrorOverlay::reset();
84    ExtOnly::reset();
85    //TODO MDPComp
86}
87
88static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
89                       hwc_display_contents_1_t** displays)
90{
91    hwc_context_t* ctx = (hwc_context_t*)(dev);
92    ctx->overlayInUse = false;
93
94    reset();
95
96    //If securing of h/w in progress skip comp using overlay.
97    if(ctx->mSecuring == true) return 0;
98
99    for (uint32_t i = 0; i < numDisplays; i++) {
100        hwc_display_contents_1_t *list = displays[i];
101        //XXX: Actually handle the multiple displays
102        if (LIKELY(list && list->numHwLayers)) {
103            ctx->dpys[i] = list->dpy;
104
105            if(ctx->isPoweredDown)
106                ALOGW("SF called %s after a POWERDOWN", __FUNCTION__);
107
108            getLayerStats(ctx, list);
109            if(VideoOverlay::prepare(ctx, list)) {
110                ctx->overlayInUse = true;
111                //Nothing here
112            } else if(ExtOnly::prepare(ctx, list)) {
113                ctx->overlayInUse = true;
114            } else if(UIMirrorOverlay::prepare(ctx, list)) {
115                ctx->overlayInUse = true;
116            } else if(MDPComp::configure(dev, list)) {
117                ctx->overlayInUse = true;
118            } else if (0) {
119                //Other features
120                ctx->overlayInUse = true;
121            } else { // Else set this flag to false, otherwise video cases
122                // fail in non-overlay targets.
123                ctx->overlayInUse = false;
124            }
125        }
126    }
127
128    return 0;
129}
130
131static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
132                             int event, int enabled)
133{
134    int ret = 0;
135    hwc_context_t* ctx = (hwc_context_t*)(dev);
136    private_module_t* m = reinterpret_cast<private_module_t*>(
137                ctx->mFbDev->common.module);
138    //XXX: Handle dpy
139    switch(event) {
140        case HWC_EVENT_VSYNC:
141            if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0)
142                ret = -errno;
143
144            if(ctx->mExtDisplay->getExternalDisplay()) {
145                ret = ctx->mExtDisplay->enableHDMIVsync(enabled);
146            }
147           break;
148        default:
149            ret = -EINVAL;
150    }
151    return ret;
152}
153
154static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
155{
156    //XXX: Handle based on dpy
157    hwc_context_t* ctx = (hwc_context_t*)(dev);
158    private_module_t* m = reinterpret_cast<private_module_t*>(
159        ctx->mFbDev->common.module);
160    if(blank) {
161        ctx->mOverlay->setState(ovutils::OV_CLOSED);
162        ctx->qbuf->unlockAllPrevious();
163        ALOGD("HWC Calling POWERDOWN ...");
164        ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
165        ALOGD("HWC Done POWERDOWN ...");
166        ctx->isPoweredDown = true;
167    } else {
168        ALOGD("HWC Calling UNBLANK ...");
169        ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
170        ALOGD("HWC Done UNBLANK ...");
171        ctx->isPoweredDown = false;
172    }
173    return 0;
174}
175
176static int hwc_query(struct hwc_composer_device_1* dev,
177                     int param, int* value)
178{
179    hwc_context_t* ctx = (hwc_context_t*)(dev);
180    private_module_t* m = reinterpret_cast<private_module_t*>(
181        ctx->mFbDev->common.module);
182
183    switch (param) {
184    case HWC_BACKGROUND_LAYER_SUPPORTED:
185        // Not supported for now
186        value[0] = 0;
187        break;
188    case HWC_VSYNC_PERIOD:
189        value[0] = m->fps;
190        ALOGI("fps: %d", value[0]);
191        break;
192    default:
193        return -EINVAL;
194    }
195    return 0;
196
197}
198
199static int hwc_set(hwc_composer_device_1 *dev,
200                   size_t numDisplays,
201                   hwc_display_contents_1_t** displays)
202{
203    int ret = 0;
204    hwc_context_t* ctx = (hwc_context_t*)(dev);
205    for (uint32_t i = 0; i <numDisplays; i++) {
206        hwc_display_contents_1_t* list = displays[i];
207        //XXX: Actually handle the multiple displays
208        if (LIKELY(list)) {
209            VideoOverlay::draw(ctx, list);
210            ExtOnly::draw(ctx, list);
211            MDPComp::draw(ctx, list);
212            EGLBoolean success = eglSwapBuffers((EGLDisplay)list->dpy,
213                                                (EGLSurface)list->sur);
214            wait4fbPost(ctx);
215            //Can draw to HDMI only when fb_post is reached
216            UIMirrorOverlay::draw(ctx);
217            //HDMI commit and primary commit (PAN) happening in parallel
218            if(ctx->mExtDisplay->getExternalDisplay())
219                ctx->mExtDisplay->commit();
220            //Virtual barrier for threads to finish
221            wait4Pan(ctx);
222        } else {
223            ctx->mOverlay->setState(ovutils::OV_CLOSED);
224            ctx->qbuf->unlockAll();
225        }
226
227        if(!ctx->overlayInUse)
228            ctx->mOverlay->setState(ovutils::OV_CLOSED);
229    }
230    ctx->qbuf->unlockAllPrevious();
231    return ret;
232}
233
234static int hwc_device_close(struct hw_device_t *dev)
235{
236    if(!dev) {
237        ALOGE("%s: NULL device pointer", __FUNCTION__);
238        return -1;
239    }
240    closeContext((hwc_context_t*)dev);
241    free(dev);
242
243    return 0;
244}
245
246static int hwc_device_open(const struct hw_module_t* module, const char* name,
247                           struct hw_device_t** device)
248{
249    int status = -EINVAL;
250
251    if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
252        struct hwc_context_t *dev;
253        dev = (hwc_context_t*)malloc(sizeof(*dev));
254        memset(dev, 0, sizeof(*dev));
255
256        //Initialize hwc context
257        initContext(dev);
258
259        //Setup HWC methods
260        dev->device.common.tag     = HARDWARE_DEVICE_TAG;
261        dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
262        dev->device.common.module  = const_cast<hw_module_t*>(module);
263        dev->device.common.close   = hwc_device_close;
264        dev->device.prepare        = hwc_prepare;
265        dev->device.set            = hwc_set;
266        dev->device.eventControl   = hwc_eventControl;
267        dev->device.blank          = hwc_blank;
268        dev->device.query          = hwc_query;
269        dev->device.registerProcs  = hwc_registerProcs;
270        *device                    = &dev->device.common;
271        status = 0;
272    }
273    return status;
274}
275