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