hwc.cpp revision 640cb9421639c13248aeb30c3496cdfaec6d894c
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_fbupdate.h"
31#include "hwc_mdpcomp.h"
32#include "external.h"
33
34using namespace qhwc;
35#define VSYNC_DEBUG 0
36
37static int hwc_device_open(const struct hw_module_t* module,
38                           const char* name,
39                           struct hw_device_t** device);
40
41static struct hw_module_methods_t hwc_module_methods = {
42    open: hwc_device_open
43};
44
45hwc_module_t HAL_MODULE_INFO_SYM = {
46    common: {
47        tag: HARDWARE_MODULE_TAG,
48        version_major: 2,
49        version_minor: 0,
50        id: HWC_HARDWARE_MODULE_ID,
51        name: "Qualcomm Hardware Composer Module",
52        author: "CodeAurora Forum",
53        methods: &hwc_module_methods,
54        dso: 0,
55        reserved: {0},
56    }
57};
58
59/*
60 * Save callback functions registered to HWC
61 */
62static void hwc_registerProcs(struct hwc_composer_device_1* dev,
63                              hwc_procs_t const* procs)
64{
65    ALOGI("%s", __FUNCTION__);
66    hwc_context_t* ctx = (hwc_context_t*)(dev);
67    if(!ctx) {
68        ALOGE("%s: Invalid context", __FUNCTION__);
69        return;
70    }
71    ctx->proc = procs;
72
73    // Now that we have the functions needed, kick off
74    // the uevent & vsync threads
75    init_uevent_thread(ctx);
76    init_vsync_thread(ctx);
77}
78
79//Helper
80static void reset(hwc_context_t *ctx, int numDisplays,
81                  hwc_display_contents_1_t** displays) {
82    memset(ctx->listStats, 0, sizeof(ctx->listStats));
83    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++){
84        ctx->listStats[i].yuvIndex = -1;
85        hwc_display_contents_1_t *list = displays[i];
86        // XXX:SurfaceFlinger no longer guarantees that this
87        // value is reset on every prepare. However, for the layer
88        // cache we need to reset it.
89        // We can probably rethink that later on
90        if (LIKELY(list && list->numHwLayers > 1)) {
91            for(uint32_t j = 0; j < list->numHwLayers; j++) {
92                if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
93                    list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
94            }
95        }
96
97        if(ctx->mFBUpdate[i])
98            ctx->mFBUpdate[i]->reset();
99    }
100    VideoOverlay::reset();
101}
102
103//clear prev layer prop flags and realloc for current frame
104static void reset_layer_prop(hwc_context_t* ctx, int dpy) {
105    int layer_count = ctx->listStats[dpy].numAppLayers;
106
107    if(ctx->layerProp[dpy]) {
108       delete[] ctx->layerProp[dpy];
109       ctx->layerProp[dpy] = NULL;
110    }
111
112    if(layer_count) {
113       ctx->layerProp[dpy] = new LayerProp[layer_count];
114    }
115}
116
117static int hwc_prepare_primary(hwc_composer_device_1 *dev,
118        hwc_display_contents_1_t *list) {
119    hwc_context_t* ctx = (hwc_context_t*)(dev);
120    const int dpy = HWC_DISPLAY_PRIMARY;
121
122    if (LIKELY(list && list->numHwLayers > 1) &&
123        ctx->dpyAttr[dpy].isActive) {
124
125        uint32_t last = list->numHwLayers - 1;
126        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
127        if(fbLayer->handle) {
128            setListStats(ctx, list, dpy);
129            reset_layer_prop(ctx, dpy);
130            if(!MDPComp::configure(ctx, list)) {
131                VideoOverlay::prepare(ctx, list, dpy);
132                ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
133            }
134            ctx->mLayerCache[dpy]->updateLayerCache(list);
135        }
136    }
137    return 0;
138}
139
140static int hwc_prepare_external(hwc_composer_device_1 *dev,
141        hwc_display_contents_1_t *list) {
142    hwc_context_t* ctx = (hwc_context_t*)(dev);
143    const int dpy = HWC_DISPLAY_EXTERNAL;
144
145    if (LIKELY(list && list->numHwLayers > 1) &&
146        ctx->dpyAttr[dpy].isActive &&
147        ctx->dpyAttr[dpy].connected) {
148
149        uint32_t last = list->numHwLayers - 1;
150        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
151        if(fbLayer->handle) {
152            setListStats(ctx, list, dpy);
153            reset_layer_prop(ctx, dpy);
154            VideoOverlay::prepare(ctx, list, dpy);
155            ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
156            ctx->mLayerCache[dpy]->updateLayerCache(list);
157        }
158    }
159    return 0;
160}
161
162static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
163                       hwc_display_contents_1_t** displays)
164{
165    int ret = 0;
166    hwc_context_t* ctx = (hwc_context_t*)(dev);
167    Locker::Autolock _l(ctx->mBlankLock);
168    reset(ctx, numDisplays, displays);
169
170    ctx->mOverlay->configBegin();
171
172    for (int32_t i = numDisplays - 1; i >= 0; i--) {
173        hwc_display_contents_1_t *list = displays[i];
174        switch(i) {
175            case HWC_DISPLAY_PRIMARY:
176                ret = hwc_prepare_primary(dev, list);
177                break;
178            case HWC_DISPLAY_EXTERNAL:
179                ret = hwc_prepare_external(dev, list);
180                break;
181            default:
182                ret = -EINVAL;
183        }
184    }
185
186    ctx->mOverlay->configDone();
187    return ret;
188}
189
190static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
191                             int event, int enabled)
192{
193    int ret = 0;
194
195    hwc_context_t* ctx = (hwc_context_t*)(dev);
196    private_module_t* m = reinterpret_cast<private_module_t*>(
197                ctx->mFbDev->common.module);
198    pthread_mutex_lock(&ctx->vstate.lock);
199    switch(event) {
200        case HWC_EVENT_VSYNC:
201            if (ctx->vstate.enable == enabled)
202                break;
203            ctx->vstate.enable = !!enabled;
204            pthread_cond_signal(&ctx->vstate.cond);
205            ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s",
206                      (enabled)?"ENABLED":"DISABLED");
207            break;
208        default:
209            ret = -EINVAL;
210    }
211    pthread_mutex_unlock(&ctx->vstate.lock);
212    return ret;
213}
214
215static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
216{
217    hwc_context_t* ctx = (hwc_context_t*)(dev);
218    private_module_t* m = reinterpret_cast<private_module_t*>(
219        ctx->mFbDev->common.module);
220    Locker::Autolock _l(ctx->mBlankLock);
221    int ret = 0;
222    ALOGD("%s: Doing Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
223    switch(dpy) {
224        case HWC_DISPLAY_PRIMARY:
225            if(blank) {
226                ctx->mOverlay->configBegin();
227                ctx->mOverlay->configDone();
228                ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
229            } else {
230                ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
231            }
232            break;
233        case HWC_DISPLAY_EXTERNAL:
234            if(blank) {
235                //TODO actual
236            } else {
237            }
238            break;
239        default:
240            return -EINVAL;
241    }
242    // Enable HPD here, as during bootup unblank is called
243    // when SF is completely initialized
244    ctx->mExtDisplay->setHPD(1);
245
246    if(ret < 0) {
247        ALOGE("%s: failed. Dpy=%d, blank=%d : %s",
248                __FUNCTION__, dpy, blank, strerror(errno));
249        return ret;
250    }
251    ALOGD("%s: Done Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
252    ctx->dpyAttr[dpy].isActive = !blank;
253    return 0;
254}
255
256static int hwc_query(struct hwc_composer_device_1* dev,
257                     int param, int* value)
258{
259    hwc_context_t* ctx = (hwc_context_t*)(dev);
260    private_module_t* m = reinterpret_cast<private_module_t*>(
261        ctx->mFbDev->common.module);
262    int supported = HWC_DISPLAY_PRIMARY_BIT;
263
264    switch (param) {
265    case HWC_BACKGROUND_LAYER_SUPPORTED:
266        // Not supported for now
267        value[0] = 0;
268        break;
269    case HWC_VSYNC_PERIOD: //Not used for hwc > 1.1
270        value[0] = m->fps;
271        ALOGI("fps: %d", value[0]);
272        break;
273    case HWC_DISPLAY_TYPES_SUPPORTED:
274        if(ctx->mMDP.hasOverlay)
275            supported |= HWC_DISPLAY_EXTERNAL_BIT;
276        value[0] = supported;
277        break;
278    default:
279        return -EINVAL;
280    }
281    return 0;
282
283}
284
285static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
286    int ret = 0;
287    const int dpy = HWC_DISPLAY_PRIMARY;
288
289    if (LIKELY(list && list->numHwLayers > 1) &&
290        ctx->dpyAttr[dpy].isActive) {
291        uint32_t last = list->numHwLayers - 1;
292        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
293
294        hwc_sync(ctx, list, dpy);
295        if (!VideoOverlay::draw(ctx, list, dpy)) {
296            ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
297            ret = -1;
298        }
299        if (!MDPComp::draw(ctx, list)) {
300            ALOGE("%s: MDPComp::draw fail!", __FUNCTION__);
301            ret = -1;
302        }
303
304        //TODO We dont check for SKIP flag on this layer because we need PAN
305        //always. Last layer is always FB
306        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
307        if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) {
308            if(!(fbLayer->flags & HWC_SKIP_LAYER)) {
309                if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) {
310                    ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
311                    ret = -1;
312                }
313            }
314            if (ctx->mFbDev->post(ctx->mFbDev, fbLayer->handle)) {
315                ALOGE("%s: ctx->mFbDev->post fail!", __FUNCTION__);
316                return -1;
317            }
318        }
319    }
320    return ret;
321}
322
323static int hwc_set_external(hwc_context_t *ctx,
324        hwc_display_contents_1_t* list) {
325    int ret = 0;
326    const int dpy = HWC_DISPLAY_EXTERNAL;
327
328    Locker::Autolock _l(ctx->mExtSetLock);
329
330    if (LIKELY(list && list->numHwLayers > 1) &&
331        ctx->dpyAttr[dpy].isActive &&
332        ctx->dpyAttr[dpy].connected) {
333        uint32_t last = list->numHwLayers - 1;
334        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
335
336        hwc_sync(ctx, list, dpy);
337
338        if (!VideoOverlay::draw(ctx, list, dpy)) {
339            ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
340            ret = -1;
341        }
342
343        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
344        if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET &&
345                !(fbLayer->flags & HWC_SKIP_LAYER) && hnd) {
346            if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) {
347                ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
348                ret = -1;
349            }
350        }
351        if (!ctx->mExtDisplay->post()) {
352            ALOGE("%s: ctx->mExtDisplay->post fail!", __FUNCTION__);
353            return -1;
354        }
355    }
356    return ret;
357}
358
359static int hwc_set(hwc_composer_device_1 *dev,
360                   size_t numDisplays,
361                   hwc_display_contents_1_t** displays)
362{
363    int ret = 0;
364    hwc_context_t* ctx = (hwc_context_t*)(dev);
365    Locker::Autolock _l(ctx->mBlankLock);
366
367    for (uint32_t i = 0; i < numDisplays; i++) {
368        hwc_display_contents_1_t* list = displays[i];
369        switch(i) {
370            case HWC_DISPLAY_PRIMARY:
371                ret = hwc_set_primary(ctx, list);
372                break;
373            case HWC_DISPLAY_EXTERNAL:
374                ret = hwc_set_external(ctx, list);
375                break;
376            default:
377                ret = -EINVAL;
378        }
379    }
380    return ret;
381}
382
383int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
384        uint32_t* configs, size_t* numConfigs) {
385    int ret = 0;
386    hwc_context_t* ctx = (hwc_context_t*)(dev);
387    //in 1.1 there is no way to choose a config, report as config id # 0
388    //This config is passed to getDisplayAttributes. Ignore for now.
389    switch(disp) {
390        case HWC_DISPLAY_PRIMARY:
391            if(*numConfigs > 0) {
392                configs[0] = 0;
393                *numConfigs = 1;
394            }
395            ret = 0; //NO_ERROR
396            break;
397        case HWC_DISPLAY_EXTERNAL:
398            ret = -1; //Not connected
399            if(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
400                ret = 0; //NO_ERROR
401                if(*numConfigs > 0) {
402                    configs[0] = 0;
403                    *numConfigs = 1;
404                }
405            }
406            break;
407    }
408    return ret;
409}
410
411int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
412        uint32_t config, const uint32_t* attributes, int32_t* values) {
413
414    hwc_context_t* ctx = (hwc_context_t*)(dev);
415    //If hotpluggable displays are inactive return error
416    if(disp == HWC_DISPLAY_EXTERNAL && !ctx->dpyAttr[disp].connected) {
417        return -1;
418    }
419
420    //From HWComposer
421    static const uint32_t DISPLAY_ATTRIBUTES[] = {
422        HWC_DISPLAY_VSYNC_PERIOD,
423        HWC_DISPLAY_WIDTH,
424        HWC_DISPLAY_HEIGHT,
425        HWC_DISPLAY_DPI_X,
426        HWC_DISPLAY_DPI_Y,
427        HWC_DISPLAY_NO_ATTRIBUTE,
428    };
429
430    const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
431            sizeof(DISPLAY_ATTRIBUTES)[0]);
432
433    for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
434        switch (attributes[i]) {
435        case HWC_DISPLAY_VSYNC_PERIOD:
436            values[i] = ctx->dpyAttr[disp].vsync_period;
437            break;
438        case HWC_DISPLAY_WIDTH:
439            values[i] = ctx->dpyAttr[disp].xres;
440            ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
441                    ctx->dpyAttr[disp].xres);
442            break;
443        case HWC_DISPLAY_HEIGHT:
444            values[i] = ctx->dpyAttr[disp].yres;
445            ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
446                    ctx->dpyAttr[disp].yres);
447            break;
448        case HWC_DISPLAY_DPI_X:
449            values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
450            break;
451        case HWC_DISPLAY_DPI_Y:
452            values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
453            break;
454        default:
455            ALOGE("Unknown display attribute %d",
456                    attributes[i]);
457            return -EINVAL;
458        }
459    }
460    return 0;
461}
462
463void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
464{
465    hwc_context_t* ctx = (hwc_context_t*)(dev);
466    android::String8 buf("");
467    dumpsys_log(buf, "Qualcomm HWC state:\n");
468    dumpsys_log(buf, "  MDPVersion=%d\n", ctx->mMDP.version);
469    dumpsys_log(buf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
470    MDPComp::dump(buf);
471    //XXX: Call Other dump functions
472    strlcpy(buff, buf.string(), buff_len);
473}
474
475static int hwc_device_close(struct hw_device_t *dev)
476{
477    if(!dev) {
478        ALOGE("%s: NULL device pointer", __FUNCTION__);
479        return -1;
480    }
481    closeContext((hwc_context_t*)dev);
482    free(dev);
483
484    return 0;
485}
486
487static int hwc_device_open(const struct hw_module_t* module, const char* name,
488                           struct hw_device_t** device)
489{
490    int status = -EINVAL;
491
492    if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
493        struct hwc_context_t *dev;
494        dev = (hwc_context_t*)malloc(sizeof(*dev));
495        memset(dev, 0, sizeof(*dev));
496
497        //Initialize hwc context
498        initContext(dev);
499
500        //Setup HWC methods
501        dev->device.common.tag          = HARDWARE_DEVICE_TAG;
502        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_1;
503        dev->device.common.module       = const_cast<hw_module_t*>(module);
504        dev->device.common.close        = hwc_device_close;
505        dev->device.prepare             = hwc_prepare;
506        dev->device.set                 = hwc_set;
507        dev->device.eventControl        = hwc_eventControl;
508        dev->device.blank               = hwc_blank;
509        dev->device.query               = hwc_query;
510        dev->device.registerProcs       = hwc_registerProcs;
511        dev->device.dump                = hwc_dump;
512        dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;
513        dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
514        *device = &dev->device.common;
515        status = 0;
516    }
517    return status;
518}
519