hwc.cpp revision c4aeb6a47160792212f22edecdf1ed45e5f575f3
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
4 *
5 * Not a Contribution, Apache license notifications and license are retained
6 * for attribution purposes only.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
21#include <fcntl.h>
22#include <errno.h>
23
24#include <cutils/log.h>
25#include <cutils/atomic.h>
26#include <EGL/egl.h>
27#include <utils/Trace.h>
28#include <sys/ioctl.h>
29#include <overlay.h>
30#include <overlayRotator.h>
31#include <overlayWriteback.h>
32#include <mdp_version.h>
33#include "hwc_utils.h"
34#include "hwc_fbupdate.h"
35#include "hwc_mdpcomp.h"
36#include "hwc_dump_layers.h"
37#include "external.h"
38#include "hwc_copybit.h"
39#include "hwc_ad.h"
40#include "profiler.h"
41#include "hwc_vpuclient.h"
42
43using namespace qhwc;
44using namespace overlay;
45
46#define VSYNC_DEBUG 0
47#define BLANK_DEBUG 1
48
49static int hwc_device_open(const struct hw_module_t* module,
50                           const char* name,
51                           struct hw_device_t** device);
52
53static struct hw_module_methods_t hwc_module_methods = {
54    open: hwc_device_open
55};
56
57static void reset_panel(struct hwc_composer_device_1* dev);
58
59hwc_module_t HAL_MODULE_INFO_SYM = {
60    common: {
61        tag: HARDWARE_MODULE_TAG,
62        version_major: 2,
63        version_minor: 0,
64        id: HWC_HARDWARE_MODULE_ID,
65        name: "Qualcomm Hardware Composer Module",
66        author: "CodeAurora Forum",
67        methods: &hwc_module_methods,
68        dso: 0,
69        reserved: {0},
70    }
71};
72
73/* In case of non-hybrid WFD session, we are fooling SF by piggybacking on
74 * HDMI display ID for virtual. This helper is needed to differentiate their
75 * paths in HAL.
76 * TODO: Not needed once we have WFD client working on top of Google API's */
77
78static int getDpyforExternalDisplay(hwc_context_t *ctx, int dpy) {
79    if(dpy == HWC_DISPLAY_EXTERNAL && ctx->mVirtualonExtActive)
80        return HWC_DISPLAY_VIRTUAL;
81    return dpy;
82}
83
84/*
85 * Save callback functions registered to HWC
86 */
87static void hwc_registerProcs(struct hwc_composer_device_1* dev,
88                              hwc_procs_t const* procs)
89{
90    ALOGI("%s", __FUNCTION__);
91    hwc_context_t* ctx = (hwc_context_t*)(dev);
92    if(!ctx) {
93        ALOGE("%s: Invalid context", __FUNCTION__);
94        return;
95    }
96    ctx->proc = procs;
97
98    // Now that we have the functions needed, kick off
99    // the uevent & vsync threads
100    init_uevent_thread(ctx);
101    init_vsync_thread(ctx);
102}
103
104//Helper
105static void reset(hwc_context_t *ctx, int numDisplays,
106                  hwc_display_contents_1_t** displays) {
107    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
108        hwc_display_contents_1_t *list = displays[i];
109        // XXX:SurfaceFlinger no longer guarantees that this
110        // value is reset on every prepare. However, for the layer
111        // cache we need to reset it.
112        // We can probably rethink that later on
113        if (LIKELY(list && list->numHwLayers > 1)) {
114            for(uint32_t j = 0; j < list->numHwLayers; j++) {
115                if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
116                    list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
117            }
118        }
119
120        if(ctx->mFBUpdate[i])
121            ctx->mFBUpdate[i]->reset();
122        if(ctx->mCopyBit[i])
123            ctx->mCopyBit[i]->reset();
124        if(ctx->mLayerRotMap[i])
125            ctx->mLayerRotMap[i]->reset();
126    }
127
128    ctx->mAD->reset();
129    MDPComp::reset();
130}
131
132//clear prev layer prop flags and realloc for current frame
133static void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers) {
134    if(ctx->layerProp[dpy]) {
135       delete[] ctx->layerProp[dpy];
136       ctx->layerProp[dpy] = NULL;
137    }
138    ctx->layerProp[dpy] = new LayerProp[numAppLayers];
139}
140
141static void handleGeomChange(hwc_context_t *ctx, int dpy,
142        hwc_display_contents_1_t *list) {
143    /* No point to calling overlay_set on MDP3 */
144    if(list->flags & HWC_GEOMETRY_CHANGED &&
145            ctx->mMDP.version >= qdutils::MDP_V4_0) {
146        ctx->mOverlay->forceSet(dpy);
147    }
148}
149
150static int hwc_prepare_primary(hwc_composer_device_1 *dev,
151        hwc_display_contents_1_t *list) {
152    ATRACE_CALL();
153    hwc_context_t* ctx = (hwc_context_t*)(dev);
154    const int dpy = HWC_DISPLAY_PRIMARY;
155    if (LIKELY(list && list->numHwLayers > 1) &&
156            ctx->dpyAttr[dpy].isActive) {
157        reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
158        handleGeomChange(ctx, dpy, list);
159        setListStats(ctx, list, dpy);
160#ifdef VPU_TARGET
161        ctx->mVPUClient->prepare(ctx, list);
162#endif
163        if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
164            const int fbZ = 0;
165            ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
166        }
167        if (ctx->mMDP.version < qdutils::MDP_V4_0) {
168            if(ctx->mCopyBit[dpy])
169                ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
170        }
171    }
172    return 0;
173}
174
175static int hwc_prepare_external(hwc_composer_device_1 *dev,
176        hwc_display_contents_1_t *list) {
177    ATRACE_CALL();
178    hwc_context_t* ctx = (hwc_context_t*)(dev);
179    const int dpy = HWC_DISPLAY_EXTERNAL;
180
181    if (LIKELY(list && list->numHwLayers > 1) &&
182            ctx->dpyAttr[dpy].isActive &&
183            ctx->dpyAttr[dpy].connected) {
184        reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
185        handleGeomChange(ctx, dpy, list);
186        if(!ctx->dpyAttr[dpy].isPause) {
187            ctx->dpyAttr[dpy].isConfiguring = false;
188            setListStats(ctx, list, dpy);
189            if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
190                const int fbZ = 0;
191                ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
192            }
193
194            if(ctx->listStats[dpy].isDisplayAnimating) {
195                // Mark all app layers as HWC_OVERLAY for external during
196                // animation, so that SF doesnt draw it on FB
197                for(int i = 0 ;i < ctx->listStats[dpy].numAppLayers; i++) {
198                    hwc_layer_1_t *layer = &list->hwLayers[i];
199                    layer->compositionType = HWC_OVERLAY;
200                }
201            }
202        } else {
203            // External Display is in Pause state.
204            // ToDo:
205            // Mark all application layers as OVERLAY so that
206            // GPU will not compose. This is done for power
207            // optimization
208        }
209    }
210    return 0;
211}
212
213static int hwc_prepare_virtual(hwc_composer_device_1 *dev,
214        hwc_display_contents_1_t *list) {
215    ATRACE_CALL();
216
217    hwc_context_t* ctx = (hwc_context_t*)(dev);
218    const int dpy = HWC_DISPLAY_VIRTUAL;
219
220    if (LIKELY(list && list->numHwLayers > 1) &&
221            ctx->dpyAttr[dpy].isActive &&
222            ctx->dpyAttr[dpy].connected) {
223        reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
224        handleGeomChange(ctx, dpy, list);
225        if(!ctx->dpyAttr[dpy].isPause) {
226            ctx->dpyAttr[dpy].isConfiguring = false;
227            setListStats(ctx, list, dpy);
228            if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
229                const int fbZ = 0;
230                ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
231            }
232
233            if(ctx->listStats[dpy].isDisplayAnimating) {
234                // Mark all app layers as HWC_OVERLAY for virtual during
235                // animation, so that SF doesnt draw it on FB
236                for(int i = 0 ;i < ctx->listStats[dpy].numAppLayers; i++) {
237                    hwc_layer_1_t *layer = &list->hwLayers[i];
238                    layer->compositionType = HWC_OVERLAY;
239                }
240            }
241        } else {
242            // Virtual Display is in Pause state.
243            // ToDo:
244            // Mark all application layers as OVERLAY so that
245            // GPU will not compose. This is done for power
246            // optimization
247        }
248    }
249    return 0;
250}
251
252
253static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
254                       hwc_display_contents_1_t** displays)
255{
256    int ret = 0;
257    hwc_context_t* ctx = (hwc_context_t*)(dev);
258
259    if (ctx->mPanelResetStatus) {
260        ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__);
261        reset_panel(dev);
262    }
263
264    //Will be unlocked at the end of set
265    ctx->mDrawLock.lock();
266    reset(ctx, numDisplays, displays);
267
268    ctx->mOverlay->configBegin();
269    ctx->mRotMgr->configBegin();
270    overlay::Writeback::configBegin();
271
272    for (int32_t i = numDisplays; i >= 0; i--) {
273        hwc_display_contents_1_t *list = displays[i];
274        int dpy = getDpyforExternalDisplay(ctx, i);
275        switch(dpy) {
276            case HWC_DISPLAY_PRIMARY:
277                ret = hwc_prepare_primary(dev, list);
278                break;
279            case HWC_DISPLAY_EXTERNAL:
280                ret = hwc_prepare_external(dev, list);
281                break;
282            case HWC_DISPLAY_VIRTUAL:
283                ret = hwc_prepare_virtual(dev, list);
284                break;
285            default:
286                ret = -EINVAL;
287        }
288    }
289
290    ctx->mOverlay->configDone();
291    ctx->mRotMgr->configDone();
292    overlay::Writeback::configDone();
293
294    return ret;
295}
296
297static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
298                             int event, int enable)
299{
300    ATRACE_CALL();
301    int ret = 0;
302    hwc_context_t* ctx = (hwc_context_t*)(dev);
303    switch(event) {
304        case HWC_EVENT_VSYNC:
305            if (ctx->vstate.enable == enable)
306                break;
307            ret = hwc_vsync_control(ctx, dpy, enable);
308            if(ret == 0)
309                ctx->vstate.enable = !!enable;
310            ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s",
311                      (enable)?"ENABLED":"DISABLED");
312            break;
313#ifdef QCOM_BSP
314        case  HWC_EVENT_ORIENTATION:
315            if(dpy == HWC_DISPLAY_PRIMARY) {
316                Locker::Autolock _l(ctx->mDrawLock);
317                // store the primary display orientation
318                // will be used in hwc_video::configure to disable
319                // rotation animation on external display
320                ctx->deviceOrientation = enable;
321            }
322            break;
323#endif
324        default:
325            ret = -EINVAL;
326    }
327    return ret;
328}
329
330static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
331{
332    ATRACE_CALL();
333    hwc_context_t* ctx = (hwc_context_t*)(dev);
334
335    Locker::Autolock _l(ctx->mDrawLock);
336    int ret = 0, value = 0;
337
338    /* In case of non-hybrid WFD session, we are fooling SF by
339     * piggybacking on HDMI display ID for virtual.
340     * TODO: Not needed once we have WFD client working on top
341     * of Google API's.
342     */
343    dpy = getDpyforExternalDisplay(ctx,dpy);
344
345    ALOGD_IF(BLANK_DEBUG, "%s: %s display: %d", __FUNCTION__,
346          blank==1 ? "Blanking":"Unblanking", dpy);
347    if(blank) {
348        // free up all the overlay pipes in use
349        // when we get a blank for either display
350        // makes sure that all pipes are freed
351        ctx->mOverlay->configBegin();
352        ctx->mOverlay->configDone();
353        ctx->mRotMgr->clear();
354        overlay::Writeback::clear();
355    }
356    switch(dpy) {
357    case HWC_DISPLAY_PRIMARY:
358        value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK;
359        if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) {
360            ALOGE("%s: Failed to handle blank event(%d) for Primary!!",
361                  __FUNCTION__, blank );
362            return -1;
363        }
364
365        if(!blank) {
366            // Enable HPD here, as during bootup unblank is called
367            // when SF is completely initialized
368            ctx->mExtDisplay->setHPD(1);
369        }
370
371        ctx->dpyAttr[dpy].isActive = !blank;
372
373        if(ctx->mVirtualonExtActive) {
374            /* if mVirtualonExtActive is true, display hal will
375             * receive unblank calls for non-hybrid WFD solution
376             * since we piggyback on HDMI.
377             * TODO: Not needed once we have WFD client working on top
378             of Google API's */
379            break;
380        }
381    case HWC_DISPLAY_VIRTUAL:
382        /* There are two ways to reach this block of code.
383
384         * Display hal has received unblank call on HWC_DISPLAY_EXTERNAL
385         and ctx->mVirtualonExtActive is true. In this case, non-hybrid
386         WFD is active. If so, getDpyforExternalDisplay will return dpy
387         as HWC_DISPLAY_VIRTUAL.
388
389         * Display hal has received unblank call on HWC_DISPLAY_PRIMARY
390         and since SF is not aware of VIRTUAL DISPLAY being handle by HWC,
391         it wont send blank / unblank events for it. We piggyback on
392         PRIMARY DISPLAY events to release mdp pipes and
393         activate/deactivate VIRTUAL DISPLAY.
394
395         * TODO: This separate case statement is not needed once we have
396         WFD client working on top of Google API's.
397
398         */
399
400        if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
401            if(blank and (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause)) {
402                int dpy = HWC_DISPLAY_VIRTUAL;
403                if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
404                    ALOGE("%s: display commit fail for virtual!", __FUNCTION__);
405                    ret = -1;
406                }
407            }
408            ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank;
409        }
410        break;
411    case HWC_DISPLAY_EXTERNAL:
412        if(blank) {
413            if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
414                ALOGE("%s: display commit fail for external!", __FUNCTION__);
415                ret = -1;
416            }
417        }
418        ctx->dpyAttr[dpy].isActive = !blank;
419        break;
420    default:
421        return -EINVAL;
422    }
423
424    ALOGD_IF(BLANK_DEBUG, "%s: Done %s display: %d", __FUNCTION__,
425          blank ? "blanking":"unblanking", dpy);
426    return ret;
427}
428
429static void reset_panel(struct hwc_composer_device_1* dev)
430{
431    int ret = 0;
432    hwc_context_t* ctx = (hwc_context_t*)(dev);
433
434    if (!ctx->mPanelResetStatus)
435        return;
436
437    ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__);
438    ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1);
439    if (ret < 0) {
440        ALOGE("%s: FBIOBLANK failed to BLANK:  %s", __FUNCTION__,
441                                                            strerror(errno));
442    }
443
444    ALOGD("%s: calling UNBLANK DISPLAY and enabling vsync", __FUNCTION__);
445    ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 0);
446    if (ret < 0) {
447        ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
448                                                            strerror(errno));
449    }
450    hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
451
452    ctx->mPanelResetStatus = false;
453}
454
455
456static int hwc_query(struct hwc_composer_device_1* dev,
457                     int param, int* value)
458{
459    hwc_context_t* ctx = (hwc_context_t*)(dev);
460    int supported = HWC_DISPLAY_PRIMARY_BIT;
461
462    switch (param) {
463    case HWC_BACKGROUND_LAYER_SUPPORTED:
464        // Not supported for now
465        value[0] = 0;
466        break;
467    case HWC_DISPLAY_TYPES_SUPPORTED:
468        if(ctx->mMDP.hasOverlay)
469            supported |= HWC_DISPLAY_EXTERNAL_BIT;
470        value[0] = supported;
471        break;
472    case HWC_FORMAT_RB_SWAP:
473        value[0] = 1;
474        break;
475    case HWC_COLOR_FILL:
476        value[0] = 1;
477        break;
478    default:
479        return -EINVAL;
480    }
481    return 0;
482
483}
484
485
486static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
487    ATRACE_CALL();
488    int ret = 0;
489    const int dpy = HWC_DISPLAY_PRIMARY;
490    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) {
491        uint32_t last = list->numHwLayers - 1;
492        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
493        int fd = -1; //FenceFD from the Copybit(valid in async mode)
494        bool copybitDone = false;
495        if(ctx->mCopyBit[dpy])
496            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
497        if(list->numHwLayers > 1)
498            hwc_sync(ctx, list, dpy, fd);
499
500        // Dump the layers for primary
501        if(ctx->mHwcDebug[dpy])
502            ctx->mHwcDebug[dpy]->dumpLayers(list);
503
504        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
505            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
506            ret = -1;
507        }
508#ifdef VPU_TARGET
509        ctx->mVPUClient->draw(ctx, list);
510#endif
511
512        //TODO We dont check for SKIP flag on this layer because we need PAN
513        //always. Last layer is always FB
514        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
515        if(copybitDone) {
516            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
517        }
518
519        if(hnd) {
520            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
521                ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
522                ret = -1;
523            }
524        }
525
526        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd,
527                                            ctx->listStats[dpy].roi)) {
528            ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
529            ret = -1;
530        }
531    }
532
533    closeAcquireFds(list);
534    return ret;
535}
536
537static int hwc_set_external(hwc_context_t *ctx,
538                            hwc_display_contents_1_t* list)
539{
540    ATRACE_CALL();
541    int ret = 0;
542
543    const int dpy = HWC_DISPLAY_EXTERNAL;
544
545
546    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
547        ctx->dpyAttr[dpy].connected &&
548        !ctx->dpyAttr[dpy].isPause) {
549        uint32_t last = list->numHwLayers - 1;
550        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
551        int fd = -1; //FenceFD from the Copybit(valid in async mode)
552        bool copybitDone = false;
553        if(ctx->mCopyBit[dpy])
554            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
555
556        if(list->numHwLayers > 1)
557            hwc_sync(ctx, list, dpy, fd);
558
559        // Dump the layers for external
560        if(ctx->mHwcDebug[dpy])
561            ctx->mHwcDebug[dpy]->dumpLayers(list);
562
563        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
564            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
565            ret = -1;
566        }
567
568        int extOnlyLayerIndex =
569                ctx->listStats[dpy].extOnlyLayerIndex;
570
571        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
572        if(extOnlyLayerIndex!= -1) {
573            hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
574            hnd = (private_handle_t *)extLayer->handle;
575        } else if(copybitDone) {
576            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
577        }
578
579        if(hnd && !isYuvBuffer(hnd)) {
580            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
581                ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
582                ret = -1;
583            }
584        }
585
586        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
587            ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
588            ret = -1;
589        }
590    }
591
592    closeAcquireFds(list);
593    return ret;
594}
595
596static int hwc_set_virtual(hwc_context_t *ctx,
597                            hwc_display_contents_1_t* list)
598{
599    ATRACE_CALL();
600    int ret = 0;
601
602    const int dpy = HWC_DISPLAY_VIRTUAL;
603
604
605    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
606            ctx->dpyAttr[dpy].connected &&
607            !ctx->dpyAttr[dpy].isPause) {
608        uint32_t last = list->numHwLayers - 1;
609        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
610        int fd = -1; //FenceFD from the Copybit(valid in async mode)
611        bool copybitDone = false;
612        if(ctx->mCopyBit[dpy])
613            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
614
615        if(list->numHwLayers > 1)
616            hwc_sync(ctx, list, dpy, fd);
617
618            // Dump the layers for virtual
619            if(ctx->mHwcDebug[dpy])
620                ctx->mHwcDebug[dpy]->dumpLayers(list);
621
622        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
623            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
624            ret = -1;
625        }
626
627        int extOnlyLayerIndex =
628            ctx->listStats[dpy].extOnlyLayerIndex;
629
630        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
631        if(extOnlyLayerIndex!= -1) {
632            hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
633            hnd = (private_handle_t *)extLayer->handle;
634        } else if(copybitDone) {
635            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
636        }
637
638        if(hnd && !isYuvBuffer(hnd)) {
639            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
640                ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
641                ret = -1;
642            }
643        }
644
645        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
646            ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
647            ret = -1;
648        }
649    }
650
651    closeAcquireFds(list);
652
653    if (list && !ctx->mVirtualonExtActive && (list->retireFenceFd < 0) ) {
654        // SF assumes HWC waits for the acquire fence and returns a new fence
655        // that signals when we're done. Since we don't wait, and also don't
656        // touch the buffer, we can just handle the acquire fence back to SF
657        // as the retire fence.
658        list->retireFenceFd = list->outbufAcquireFenceFd;
659    }
660
661    return ret;
662}
663
664
665static int hwc_set(hwc_composer_device_1 *dev,
666                   size_t numDisplays,
667                   hwc_display_contents_1_t** displays)
668{
669    int ret = 0;
670    hwc_context_t* ctx = (hwc_context_t*)(dev);
671    for (uint32_t i = 0; i <= numDisplays; i++) {
672        hwc_display_contents_1_t* list = displays[i];
673        int dpy = getDpyforExternalDisplay(ctx, i);
674        switch(dpy) {
675            case HWC_DISPLAY_PRIMARY:
676                ret = hwc_set_primary(ctx, list);
677                break;
678            case HWC_DISPLAY_EXTERNAL:
679                ret = hwc_set_external(ctx, list);
680                break;
681            case HWC_DISPLAY_VIRTUAL:
682                ret = hwc_set_virtual(ctx, list);
683                break;
684            default:
685                ret = -EINVAL;
686        }
687    }
688    // This is only indicative of how many times SurfaceFlinger posts
689    // frames to the display.
690    CALC_FPS();
691    MDPComp::resetIdleFallBack();
692    ctx->mVideoTransFlag = false;
693    if(ctx->mRotMgr->getNumActiveSessions() == 0)
694        Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
695    //Was locked at the beginning of prepare
696    ctx->mDrawLock.unlock();
697    return ret;
698}
699
700int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
701        uint32_t* configs, size_t* numConfigs) {
702    int ret = 0;
703    hwc_context_t* ctx = (hwc_context_t*)(dev);
704    disp = getDpyforExternalDisplay(ctx, disp);
705    //in 1.1 there is no way to choose a config, report as config id # 0
706    //This config is passed to getDisplayAttributes. Ignore for now.
707    switch(disp) {
708        case HWC_DISPLAY_PRIMARY:
709            if(*numConfigs > 0) {
710                configs[0] = 0;
711                *numConfigs = 1;
712            }
713            ret = 0; //NO_ERROR
714            break;
715        case HWC_DISPLAY_EXTERNAL:
716        case HWC_DISPLAY_VIRTUAL:
717            ret = -1; //Not connected
718            if(ctx->dpyAttr[disp].connected) {
719                ret = 0; //NO_ERROR
720                if(*numConfigs > 0) {
721                    configs[0] = 0;
722                    *numConfigs = 1;
723                }
724            }
725            break;
726    }
727    return ret;
728}
729
730int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
731        uint32_t config, const uint32_t* attributes, int32_t* values) {
732
733    hwc_context_t* ctx = (hwc_context_t*)(dev);
734    disp = getDpyforExternalDisplay(ctx, disp);
735    //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error
736    if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) {
737        return -1;
738    }
739
740    //From HWComposer
741    static const uint32_t DISPLAY_ATTRIBUTES[] = {
742        HWC_DISPLAY_VSYNC_PERIOD,
743        HWC_DISPLAY_WIDTH,
744        HWC_DISPLAY_HEIGHT,
745        HWC_DISPLAY_DPI_X,
746        HWC_DISPLAY_DPI_Y,
747        HWC_DISPLAY_NO_ATTRIBUTE,
748    };
749
750    const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
751            sizeof(DISPLAY_ATTRIBUTES)[0]);
752
753    for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
754        switch (attributes[i]) {
755        case HWC_DISPLAY_VSYNC_PERIOD:
756            values[i] = ctx->dpyAttr[disp].vsync_period;
757            break;
758        case HWC_DISPLAY_WIDTH:
759            values[i] = ctx->dpyAttr[disp].xres;
760            ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
761                    ctx->dpyAttr[disp].xres);
762            break;
763        case HWC_DISPLAY_HEIGHT:
764            values[i] = ctx->dpyAttr[disp].yres;
765            ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
766                    ctx->dpyAttr[disp].yres);
767            break;
768        case HWC_DISPLAY_DPI_X:
769            values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
770            break;
771        case HWC_DISPLAY_DPI_Y:
772            values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
773            break;
774        default:
775            ALOGE("Unknown display attribute %d",
776                    attributes[i]);
777            return -EINVAL;
778        }
779    }
780    return 0;
781}
782
783void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
784{
785    hwc_context_t* ctx = (hwc_context_t*)(dev);
786    Locker::Autolock _l(ctx->mDrawLock);
787    android::String8 aBuf("");
788    dumpsys_log(aBuf, "Qualcomm HWC state:\n");
789    dumpsys_log(aBuf, "  MDPVersion=%d\n", ctx->mMDP.version);
790    dumpsys_log(aBuf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
791    for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
792        if(ctx->mMDPComp[dpy])
793            ctx->mMDPComp[dpy]->dump(aBuf);
794    }
795    char ovDump[2048] = {'\0'};
796    ctx->mOverlay->getDump(ovDump, 2048);
797    dumpsys_log(aBuf, ovDump);
798    ovDump[0] = '\0';
799    ctx->mRotMgr->getDump(ovDump, 1024);
800    dumpsys_log(aBuf, ovDump);
801    ovDump[0] = '\0';
802    if(Writeback::getDump(ovDump, 1024)) {
803        dumpsys_log(aBuf, ovDump);
804        ovDump[0] = '\0';
805    }
806    strlcpy(buff, aBuf.string(), buff_len);
807}
808
809static int hwc_device_close(struct hw_device_t *dev)
810{
811    if(!dev) {
812        ALOGE("%s: NULL device pointer", __FUNCTION__);
813        return -1;
814    }
815    closeContext((hwc_context_t*)dev);
816    free(dev);
817
818    return 0;
819}
820
821static int hwc_device_open(const struct hw_module_t* module, const char* name,
822                           struct hw_device_t** device)
823{
824    int status = -EINVAL;
825
826    if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
827        struct hwc_context_t *dev;
828        dev = (hwc_context_t*)malloc(sizeof(*dev));
829        memset(dev, 0, sizeof(*dev));
830
831        //Initialize hwc context
832        initContext(dev);
833
834        //Setup HWC methods
835        dev->device.common.tag          = HARDWARE_DEVICE_TAG;
836        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_3;
837        dev->device.common.module       = const_cast<hw_module_t*>(module);
838        dev->device.common.close        = hwc_device_close;
839        dev->device.prepare             = hwc_prepare;
840        dev->device.set                 = hwc_set;
841        dev->device.eventControl        = hwc_eventControl;
842        dev->device.blank               = hwc_blank;
843        dev->device.query               = hwc_query;
844        dev->device.registerProcs       = hwc_registerProcs;
845        dev->device.dump                = hwc_dump;
846        dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;
847        dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
848        *device = &dev->device.common;
849        status = 0;
850    }
851    return status;
852}
853