hwc.cpp revision a71a7ecd0323a16fe7728271474f8b7056c679d8
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012, Code Aurora Forum. 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 "hwc_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
78static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
79                       hwc_display_contents_1_t** displays)
80{
81    hwc_context_t* ctx = (hwc_context_t*)(dev);
82    ctx->overlayInUse = false;
83
84    //Prepare is called after a vsync, so unlock previous buffers here.
85    ctx->qbuf->unlockAllPrevious();
86
87    for (uint32_t i = 0; i <numDisplays; i++) {
88        hwc_display_contents_1_t* list = displays[i];
89        ctx->dpys[i] = list->dpy;
90        //XXX: Actually handle the multiple displays
91        if (LIKELY(list)) {
92            //reset for this draw round
93            VideoOverlay::reset();
94            ExtOnly::reset();
95
96            getLayerStats(ctx, list);
97            if(VideoOverlay::prepare(ctx, list)) {
98                ctx->overlayInUse = true;
99                //Nothing here
100            } else if(ExtOnly::prepare(ctx, list)) {
101                ctx->overlayInUse = true;
102            } else if(UIMirrorOverlay::prepare(ctx, list)) {
103                ctx->overlayInUse = true;
104            } else if(MDPComp::configure(dev, list)) {
105                ctx->overlayInUse = true;
106            } else if (0) {
107                //Other features
108                ctx->overlayInUse = true;
109            } else { // Else set this flag to false, otherwise video cases
110                // fail in non-overlay targets.
111                ctx->overlayInUse = false;
112            }
113        }
114    }
115
116    return 0;
117}
118
119static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
120                             int event, int enabled)
121{
122    int ret = 0;
123    hwc_context_t* ctx = (hwc_context_t*)(dev);
124    private_module_t* m = reinterpret_cast<private_module_t*>(
125                ctx->mFbDev->common.module);
126    //XXX: Handle dpy
127    switch(event) {
128        case HWC_EVENT_VSYNC:
129            if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0)
130                ret = -errno;
131
132            if(ctx->mExtDisplay->getExternalDisplay()) {
133                ret = ctx->mExtDisplay->enableHDMIVsync(enabled);
134            }
135           break;
136        default:
137            ret = -EINVAL;
138    }
139    return ret;
140}
141
142static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
143{
144    //XXX: Handle based on dpy
145    hwc_context_t* ctx = (hwc_context_t*)(dev);
146    private_module_t* m = reinterpret_cast<private_module_t*>(
147        ctx->mFbDev->common.module);
148    if(blank) {
149        ctx->mOverlay->setState(ovutils::OV_CLOSED);
150        ctx->qbuf->unlockAllPrevious();
151        ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
152    } else {
153        ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
154    }
155    return 0;
156}
157
158static int hwc_query(struct hwc_composer_device_1* dev,
159                     int param, int* value)
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
165    switch (param) {
166    case HWC_BACKGROUND_LAYER_SUPPORTED:
167        // Not supported for now
168        value[0] = 0;
169        break;
170    case HWC_VSYNC_PERIOD:
171        value[0] = 1000000000.0 / m->fps;
172        ALOGI("fps: %d", value[0]);
173        break;
174    default:
175        return -EINVAL;
176    }
177    return 0;
178
179}
180
181static int hwc_set(hwc_composer_device_1 *dev,
182                   size_t numDisplays,
183                   hwc_display_contents_1_t** displays)
184{
185    int ret = 0;
186    hwc_context_t* ctx = (hwc_context_t*)(dev);
187    for (uint32_t i = 0; i <numDisplays; i++) {
188        hwc_display_contents_1_t* list = displays[i];
189        //XXX: Actually handle the multiple displays
190        if (LIKELY(list)) {
191            VideoOverlay::draw(ctx, list);
192            ExtOnly::draw(ctx, list);
193            MDPComp::draw(ctx, list);
194            EGLBoolean success = eglSwapBuffers((EGLDisplay)list->dpy,
195                                                (EGLSurface)list->sur);
196            wait4fbPost(ctx);
197            //Can draw to HDMI only when fb_post is reached
198            UIMirrorOverlay::draw(ctx);
199            //HDMI commit and primary commit (PAN) happening in parallel
200            if(ctx->mExtDisplay->getExternalDisplay())
201                ctx->mExtDisplay->commit();
202            //Virtual barrier for threads to finish
203            wait4Pan(ctx);
204        } else {
205            ctx->mOverlay->setState(ovutils::OV_CLOSED);
206            ctx->qbuf->unlockAll();
207        }
208
209        if(!ctx->overlayInUse)
210            ctx->mOverlay->setState(ovutils::OV_CLOSED);
211    }
212    return ret;
213}
214
215static int hwc_device_close(struct hw_device_t *dev)
216{
217    if(!dev) {
218        ALOGE("%s: NULL device pointer", __FUNCTION__);
219        return -1;
220    }
221    closeContext((hwc_context_t*)dev);
222    free(dev);
223
224    return 0;
225}
226
227static int hwc_device_open(const struct hw_module_t* module, const char* name,
228                           struct hw_device_t** device)
229{
230    int status = -EINVAL;
231
232    if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
233        struct hwc_context_t *dev;
234        dev = (hwc_context_t*)malloc(sizeof(*dev));
235        memset(dev, 0, sizeof(*dev));
236
237        //Initialize hwc context
238        initContext(dev);
239
240        //Setup HWC methods
241        dev->device.common.tag     = HARDWARE_DEVICE_TAG;
242        dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
243        dev->device.common.module  = const_cast<hw_module_t*>(module);
244        dev->device.common.close   = hwc_device_close;
245        dev->device.prepare        = hwc_prepare;
246        dev->device.set            = hwc_set;
247        dev->device.eventControl   = hwc_eventControl;
248        dev->device.blank          = hwc_blank;
249        dev->device.query          = hwc_query;
250        dev->device.registerProcs  = hwc_registerProcs;
251        *device                    = &dev->device.common;
252        status = 0;
253    }
254    return status;
255}
256