hwc.cpp revision 3d3705af561ebe7182b23fdc81e0b755d22b11eb
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012-2014, 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_virtual.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
104static void setPaddingRound(hwc_context_t *ctx, int numDisplays,
105                            hwc_display_contents_1_t** displays) {
106    ctx->isPaddingRound = false;
107    for(int i = 0; i < numDisplays; i++) {
108        hwc_display_contents_1_t *list = displays[i];
109        if (LIKELY(list && list->numHwLayers > 0)) {
110            if((ctx->mPrevHwLayerCount[i] == 1 or
111                ctx->mPrevHwLayerCount[i] == 0) and
112               (list->numHwLayers > 1)) {
113                /* If the previous cycle for dpy 'i' has 0 AppLayers and the
114                 * current cycle has atleast 1 AppLayer, padding round needs
115                 * to be invoked in current cycle on all the active displays
116                 * to free up the resources.
117                 */
118                ctx->isPaddingRound = true;
119            }
120            ctx->mPrevHwLayerCount[i] = (int)list->numHwLayers;
121        } else {
122            ctx->mPrevHwLayerCount[i] = 0;
123        }
124    }
125}
126
127/* Based on certain conditions, isPaddingRound will be set
128 * to make this function self-contained */
129static void setDMAState(hwc_context_t *ctx, int numDisplays,
130                        hwc_display_contents_1_t** displays) {
131
132    if(ctx->mRotMgr->getNumActiveSessions() == 0)
133        Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
134
135    for(int i = 0; i < numDisplays; i++) {
136        hwc_display_contents_1_t *list = displays[i];
137        if (LIKELY(list && list->numHwLayers > 0)) {
138            for(size_t j = 0; j < list->numHwLayers; j++) {
139                if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
140                {
141                    hwc_layer_1_t const* layer = &list->hwLayers[i];
142                    private_handle_t *hnd = (private_handle_t *)layer->handle;
143
144                    /* If a video layer requires rotation, set the DMA state
145                     * to BLOCK_MODE */
146
147                    if (UNLIKELY(isYuvBuffer(hnd)) && canUseRotator(ctx,i) &&
148                        (layer->transform & HWC_TRANSFORM_ROT_90)) {
149                        if(not qdutils::MDPVersion::getInstance().is8x26()) {
150                            if(ctx->mOverlay->isPipeTypeAttached(
151                                             overlay::utils::OV_MDP_PIPE_DMA))
152                                ctx->isPaddingRound = true;
153                        }
154                        Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
155                    }
156                }
157            }
158            if(i) {
159                /* Uncomment the below code for testing purpose.
160                   Assuming the orientation value is in terms of HAL_TRANSFORM,
161                   this needs mapping to HAL, if its in different convention */
162
163                /* char value[PROPERTY_VALUE_MAX];
164                   property_get("sys.ext_orientation", value, "0");
165                   ctx->mExtOrientation = atoi(value);*/
166
167                if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
168                    if(ctx->mOverlay->isPipeTypeAttached(
169                                         overlay::utils::OV_MDP_PIPE_DMA)) {
170                        ctx->isPaddingRound = true;
171                    }
172                    Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
173                }
174            }
175        }
176    }
177}
178
179static void setNumActiveDisplays(hwc_context_t *ctx, int numDisplays,
180                            hwc_display_contents_1_t** displays) {
181
182    ctx->numActiveDisplays = 0;
183    for(int i = 0; i < numDisplays; i++) {
184        hwc_display_contents_1_t *list = displays[i];
185        if (LIKELY(list && list->numHwLayers > 0)) {
186            /* For display devices like SSD and screenrecord, we cannot
187             * rely on isActive and connected attributes of dpyAttr to
188             * determine if the displaydevice is active. Hence in case if
189             * the layer-list is non-null and numHwLayers > 0, we assume
190             * the display device to be active.
191             */
192            ctx->numActiveDisplays += 1;
193        }
194    }
195}
196
197static void reset(hwc_context_t *ctx, int numDisplays,
198                  hwc_display_contents_1_t** displays) {
199
200
201    for(int i = 0; i < numDisplays; i++) {
202        hwc_display_contents_1_t *list = displays[i];
203        // XXX:SurfaceFlinger no longer guarantees that this
204        // value is reset on every prepare. However, for the layer
205        // cache we need to reset it.
206        // We can probably rethink that later on
207        if (LIKELY(list && list->numHwLayers > 0)) {
208            for(size_t j = 0; j < list->numHwLayers; j++) {
209                if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
210                    list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
211            }
212            ctx->mPrevHwLayerCount[i] = (int)list->numHwLayers;
213        } else {
214            ctx->mPrevHwLayerCount[i] = 0;
215        }
216
217        if(ctx->mFBUpdate[i])
218            ctx->mFBUpdate[i]->reset();
219        if(ctx->mCopyBit[i])
220            ctx->mCopyBit[i]->reset();
221        if(ctx->mLayerRotMap[i])
222            ctx->mLayerRotMap[i]->reset();
223    }
224
225    ctx->mAD->reset();
226    MDPComp::reset();
227    if(ctx->mHWCVirtual)
228        ctx->mHWCVirtual->destroy(ctx, numDisplays, displays);
229}
230
231bool isEqual(float f1, float f2) {
232        return ((int)(f1*100) == (int)(f2*100)) ? true : false;
233}
234
235static void scaleDisplayFrame(hwc_context_t *ctx, int dpy,
236                            hwc_display_contents_1_t *list) {
237    uint32_t origXres = ctx->dpyAttr[dpy].xres_orig;
238    uint32_t origYres = ctx->dpyAttr[dpy].yres_orig;
239    uint32_t fakeXres = ctx->dpyAttr[dpy].xres;
240    uint32_t fakeYres = ctx->dpyAttr[dpy].yres;
241    float xresRatio = (float)origXres / (float)fakeXres;
242    float yresRatio = (float)origYres / (float)fakeYres;
243    for (size_t i = 0; i < list->numHwLayers; i++) {
244        hwc_layer_1_t *layer = &list->hwLayers[i];
245        hwc_rect_t& displayFrame = layer->displayFrame;
246        hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
247        uint32_t layerWidth = displayFrame.right - displayFrame.left;
248        uint32_t layerHeight = displayFrame.bottom - displayFrame.top;
249        uint32_t sourceWidth = sourceCrop.right - sourceCrop.left;
250        uint32_t sourceHeight = sourceCrop.bottom - sourceCrop.top;
251
252        if (isEqual(((float)layerWidth / (float)sourceWidth), xresRatio) &&
253                isEqual(((float)layerHeight / (float)sourceHeight), yresRatio))
254            break;
255
256        displayFrame.left = (int)(xresRatio * (float)displayFrame.left);
257        displayFrame.top = (int)(yresRatio * (float)displayFrame.top);
258        displayFrame.right = (int)((float)displayFrame.left +
259                                   (float)layerWidth * xresRatio);
260        displayFrame.bottom = (int)((float)displayFrame.top +
261                                    (float)layerHeight * yresRatio);
262    }
263}
264
265static int hwc_prepare_primary(hwc_composer_device_1 *dev,
266        hwc_display_contents_1_t *list) {
267    ATRACE_CALL();
268    hwc_context_t* ctx = (hwc_context_t*)(dev);
269    const int dpy = HWC_DISPLAY_PRIMARY;
270    bool fbComp = false;
271    if (LIKELY(list && list->numHwLayers > 1) &&
272            ctx->dpyAttr[dpy].isActive) {
273
274        if (ctx->dpyAttr[dpy].customFBSize)
275            scaleDisplayFrame(ctx, dpy, list);
276
277        reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
278        setListStats(ctx, list, dpy);
279
280        fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
281
282        if (fbComp) {
283            const int fbZ = 0;
284            ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
285        }
286
287        if (ctx->mMDP.version < qdutils::MDP_V4_0) {
288            if(ctx->mCopyBit[dpy])
289                ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
290        }
291        setGPUHint(ctx, list);
292    }
293    return 0;
294}
295
296static int hwc_prepare_external(hwc_composer_device_1 *dev,
297        hwc_display_contents_1_t *list) {
298    ATRACE_CALL();
299    hwc_context_t* ctx = (hwc_context_t*)(dev);
300    const int dpy = HWC_DISPLAY_EXTERNAL;
301
302    if (LIKELY(list && list->numHwLayers > 1) &&
303            ctx->dpyAttr[dpy].isActive &&
304            ctx->dpyAttr[dpy].connected) {
305        reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
306        if(!ctx->dpyAttr[dpy].isPause) {
307            ctx->dpyAttr[dpy].isConfiguring = false;
308            setListStats(ctx, list, dpy);
309            if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
310                const int fbZ = 0;
311                ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
312            }
313        } else {
314            /* External Display is in Pause state.
315             * Mark all application layers as OVERLAY so that
316             * GPU will not compose.
317             */
318            for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
319                hwc_layer_1_t *layer = &list->hwLayers[i];
320                layer->compositionType = HWC_OVERLAY;
321            }
322        }
323    }
324    return 0;
325}
326
327static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
328                       hwc_display_contents_1_t** displays)
329{
330    int ret = 0;
331    hwc_context_t* ctx = (hwc_context_t*)(dev);
332
333    if (ctx->mPanelResetStatus) {
334        ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__);
335        reset_panel(dev);
336    }
337
338    //Will be unlocked at the end of set
339    ctx->mDrawLock.lock();
340    setPaddingRound(ctx,numDisplays,displays);
341    setDMAState(ctx,numDisplays,displays);
342    setNumActiveDisplays(ctx,numDisplays,displays);
343    reset(ctx, (int)numDisplays, displays);
344
345    ctx->mOverlay->configBegin();
346    ctx->mRotMgr->configBegin();
347    overlay::Writeback::configBegin();
348
349    for (int32_t i = ((int32_t)numDisplays-1); i >=0 ; i--) {
350        hwc_display_contents_1_t *list = displays[i];
351        int dpy = getDpyforExternalDisplay(ctx, i);
352        switch(dpy) {
353            case HWC_DISPLAY_PRIMARY:
354                ret = hwc_prepare_primary(dev, list);
355                break;
356            case HWC_DISPLAY_EXTERNAL:
357                ret = hwc_prepare_external(dev, list);
358                break;
359            case HWC_DISPLAY_VIRTUAL:
360                if(ctx->mHWCVirtual)
361                    ret = ctx->mHWCVirtual->prepare(dev, list);
362                break;
363            default:
364                ret = -EINVAL;
365        }
366    }
367
368    ctx->mOverlay->configDone();
369    ctx->mRotMgr->configDone();
370    overlay::Writeback::configDone();
371
372    return ret;
373}
374
375static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
376                             int event, int enable)
377{
378    ATRACE_CALL();
379    int ret = 0;
380    hwc_context_t* ctx = (hwc_context_t*)(dev);
381    switch(event) {
382        case HWC_EVENT_VSYNC:
383            if (ctx->vstate.enable == enable)
384                break;
385            ret = hwc_vsync_control(ctx, dpy, enable);
386            if(ret == 0)
387                ctx->vstate.enable = !!enable;
388            ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s",
389                      (enable)?"ENABLED":"DISABLED");
390            break;
391#ifdef QCOM_BSP
392        case  HWC_EVENT_ORIENTATION:
393            if(dpy == HWC_DISPLAY_PRIMARY) {
394                Locker::Autolock _l(ctx->mDrawLock);
395                // store the primary display orientation
396                ctx->deviceOrientation = enable;
397            }
398            break;
399#endif
400        default:
401            ret = -EINVAL;
402    }
403    return ret;
404}
405
406static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
407{
408    ATRACE_CALL();
409    hwc_context_t* ctx = (hwc_context_t*)(dev);
410
411    Locker::Autolock _l(ctx->mDrawLock);
412    int ret = 0, value = 0;
413
414    /* In case of non-hybrid WFD session, we are fooling SF by
415     * piggybacking on HDMI display ID for virtual.
416     * TODO: Not needed once we have WFD client working on top
417     * of Google API's.
418     */
419    dpy = getDpyforExternalDisplay(ctx,dpy);
420
421    ALOGD_IF(BLANK_DEBUG, "%s: %s display: %d", __FUNCTION__,
422          blank==1 ? "Blanking":"Unblanking", dpy);
423    if(blank) {
424        // free up all the overlay pipes in use
425        // when we get a blank for either display
426        // makes sure that all pipes are freed
427        ctx->mOverlay->configBegin();
428        ctx->mOverlay->configDone();
429        ctx->mRotMgr->clear();
430        // If VDS is connected, do not clear WB object as it
431        // will end up detaching IOMMU. This is required
432        // to send black frame to WFD sink on power suspend.
433        // Note: With this change, we keep the WriteBack object
434        // alive on power suspend for AD use case.
435    }
436    switch(dpy) {
437    case HWC_DISPLAY_PRIMARY:
438        value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK;
439        if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) {
440            ALOGE("%s: Failed to handle blank event(%d) for Primary!!",
441                  __FUNCTION__, blank );
442            return -1;
443        }
444
445        if(!blank) {
446            // Enable HPD here, as during bootup unblank is called
447            // when SF is completely initialized
448            ctx->mExtDisplay->setHPD(1);
449        }
450
451        ctx->dpyAttr[dpy].isActive = !blank;
452
453        if(ctx->mVirtualonExtActive) {
454            /* if mVirtualonExtActive is true, display hal will
455             * receive unblank calls for non-hybrid WFD solution
456             * since we piggyback on HDMI.
457             * TODO: Not needed once we have WFD client working on top
458             of Google API's */
459            break;
460        }
461    case HWC_DISPLAY_VIRTUAL:
462        /* There are two ways to reach this block of code.
463
464         * Display hal has received unblank call on HWC_DISPLAY_EXTERNAL
465         and ctx->mVirtualonExtActive is true. In this case, non-hybrid
466         WFD is active. If so, getDpyforExternalDisplay will return dpy
467         as HWC_DISPLAY_VIRTUAL.
468
469         * Display hal has received unblank call on HWC_DISPLAY_PRIMARY
470         and since SF is not aware of VIRTUAL DISPLAY being handle by HWC,
471         it wont send blank / unblank events for it. We piggyback on
472         PRIMARY DISPLAY events to release mdp pipes and
473         activate/deactivate VIRTUAL DISPLAY.
474
475         * TODO: This separate case statement is not needed once we have
476         WFD client working on top of Google API's.
477
478         */
479
480        if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
481            if(blank and (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause)) {
482                int dpy = HWC_DISPLAY_VIRTUAL;
483                if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
484                    ALOGE("%s: display commit fail for virtual!", __FUNCTION__);
485                    ret = -1;
486                }
487            }
488            ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank;
489        }
490        break;
491    case HWC_DISPLAY_EXTERNAL:
492        if(blank) {
493            if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
494                ALOGE("%s: display commit fail for external!", __FUNCTION__);
495                ret = -1;
496            }
497        }
498        ctx->dpyAttr[dpy].isActive = !blank;
499        break;
500    default:
501        return -EINVAL;
502    }
503
504    ALOGD_IF(BLANK_DEBUG, "%s: Done %s display: %d", __FUNCTION__,
505          blank ? "blanking":"unblanking", dpy);
506    return ret;
507}
508
509static void reset_panel(struct hwc_composer_device_1* dev)
510{
511    int ret = 0;
512    hwc_context_t* ctx = (hwc_context_t*)(dev);
513
514    if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
515        ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__);
516        ctx->mPanelResetStatus = false;
517        return;
518    }
519
520    ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__);
521    ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1);
522    if (ret < 0) {
523        ALOGE("%s: FBIOBLANK failed to BLANK:  %s", __FUNCTION__,
524                                                            strerror(errno));
525    }
526
527    ALOGD("%s: calling UNBLANK DISPLAY and enabling vsync", __FUNCTION__);
528    ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 0);
529    if (ret < 0) {
530        ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
531                                                            strerror(errno));
532    }
533    hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
534
535    ctx->mPanelResetStatus = false;
536}
537
538
539static int hwc_query(struct hwc_composer_device_1* dev,
540                     int param, int* value)
541{
542    hwc_context_t* ctx = (hwc_context_t*)(dev);
543    int supported = HWC_DISPLAY_PRIMARY_BIT;
544
545    switch (param) {
546    case HWC_BACKGROUND_LAYER_SUPPORTED:
547        // Not supported for now
548        value[0] = 0;
549        break;
550    case HWC_DISPLAY_TYPES_SUPPORTED:
551        if(ctx->mMDP.hasOverlay) {
552            supported |= HWC_DISPLAY_VIRTUAL_BIT;
553            if(!(qdutils::MDPVersion::getInstance().is8x26() ||
554                        qdutils::MDPVersion::getInstance().is8x16()))
555                supported |= HWC_DISPLAY_EXTERNAL_BIT;
556        }
557        value[0] = supported;
558        break;
559    case HWC_FORMAT_RB_SWAP:
560        value[0] = 1;
561        break;
562    case HWC_COLOR_FILL:
563        value[0] = 1;
564        break;
565    default:
566        return -EINVAL;
567    }
568    return 0;
569
570}
571
572
573static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
574    ATRACE_CALL();
575    int ret = 0;
576    const int dpy = HWC_DISPLAY_PRIMARY;
577    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) {
578        size_t last = list->numHwLayers - 1;
579        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
580        int fd = -1; //FenceFD from the Copybit(valid in async mode)
581        bool copybitDone = false;
582        if(ctx->mCopyBit[dpy])
583            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
584        if(list->numHwLayers > 1)
585            hwc_sync(ctx, list, dpy, fd);
586
587        // Dump the layers for primary
588        if(ctx->mHwcDebug[dpy])
589            ctx->mHwcDebug[dpy]->dumpLayers(list);
590
591        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
592            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
593            ret = -1;
594        }
595
596        //TODO We dont check for SKIP flag on this layer because we need PAN
597        //always. Last layer is always FB
598        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
599        if(copybitDone && ctx->mMDP.version >= qdutils::MDP_V4_0) {
600            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
601        }
602
603        if(hnd) {
604            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
605                ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
606                ret = -1;
607            }
608        }
609
610        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd,
611                                            ctx->listStats[dpy].roi)) {
612            ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
613            ret = -1;
614        }
615
616    }
617
618    closeAcquireFds(list);
619    return ret;
620}
621
622static int hwc_set_external(hwc_context_t *ctx,
623                            hwc_display_contents_1_t* list)
624{
625    ATRACE_CALL();
626    int ret = 0;
627
628    const int dpy = HWC_DISPLAY_EXTERNAL;
629
630
631    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
632        ctx->dpyAttr[dpy].connected &&
633        !ctx->dpyAttr[dpy].isPause) {
634        size_t last = list->numHwLayers - 1;
635        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
636        int fd = -1; //FenceFD from the Copybit(valid in async mode)
637        bool copybitDone = false;
638        if(ctx->mCopyBit[dpy])
639            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
640
641        if(list->numHwLayers > 1)
642            hwc_sync(ctx, list, dpy, fd);
643
644        // Dump the layers for external
645        if(ctx->mHwcDebug[dpy])
646            ctx->mHwcDebug[dpy]->dumpLayers(list);
647
648        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
649            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
650            ret = -1;
651        }
652
653        int extOnlyLayerIndex =
654                ctx->listStats[dpy].extOnlyLayerIndex;
655
656        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
657        if(extOnlyLayerIndex!= -1) {
658            hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
659            hnd = (private_handle_t *)extLayer->handle;
660        } else if(copybitDone) {
661            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
662        }
663
664        if(hnd && !isYuvBuffer(hnd)) {
665            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
666                ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
667                ret = -1;
668            }
669        }
670
671        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
672            ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
673            ret = -1;
674        }
675    }
676
677    closeAcquireFds(list);
678    return ret;
679}
680
681static int hwc_set(hwc_composer_device_1 *dev,
682                   size_t numDisplays,
683                   hwc_display_contents_1_t** displays)
684{
685    int ret = 0;
686    hwc_context_t* ctx = (hwc_context_t*)(dev);
687    for (int i = 0; i < (int)numDisplays; i++) {
688        hwc_display_contents_1_t* list = displays[i];
689        int dpy = getDpyforExternalDisplay(ctx, i);
690        switch(dpy) {
691            case HWC_DISPLAY_PRIMARY:
692                ret = hwc_set_primary(ctx, list);
693                break;
694            case HWC_DISPLAY_EXTERNAL:
695                ret = hwc_set_external(ctx, list);
696                break;
697            case HWC_DISPLAY_VIRTUAL:
698                if(ctx->mHWCVirtual)
699                    ret = ctx->mHWCVirtual->set(ctx, list);
700                break;
701            default:
702                ret = -EINVAL;
703        }
704    }
705    // This is only indicative of how many times SurfaceFlinger posts
706    // frames to the display.
707    CALC_FPS();
708    MDPComp::resetIdleFallBack();
709    ctx->mVideoTransFlag = false;
710    //Was locked at the beginning of prepare
711    ctx->mDrawLock.unlock();
712    return ret;
713}
714
715int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
716        uint32_t* configs, size_t* numConfigs) {
717    int ret = 0;
718    hwc_context_t* ctx = (hwc_context_t*)(dev);
719    disp = getDpyforExternalDisplay(ctx, disp);
720    //in 1.1 there is no way to choose a config, report as config id # 0
721    //This config is passed to getDisplayAttributes. Ignore for now.
722    switch(disp) {
723        case HWC_DISPLAY_PRIMARY:
724            if(*numConfigs > 0) {
725                configs[0] = 0;
726                *numConfigs = 1;
727            }
728            ret = 0; //NO_ERROR
729            break;
730        case HWC_DISPLAY_EXTERNAL:
731        case HWC_DISPLAY_VIRTUAL:
732            ret = -1; //Not connected
733            if(ctx->dpyAttr[disp].connected) {
734                ret = 0; //NO_ERROR
735                if(*numConfigs > 0) {
736                    configs[0] = 0;
737                    *numConfigs = 1;
738                }
739            }
740            break;
741    }
742    return ret;
743}
744
745int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
746        uint32_t /*config*/, const uint32_t* attributes, int32_t* values) {
747
748    hwc_context_t* ctx = (hwc_context_t*)(dev);
749    disp = getDpyforExternalDisplay(ctx, disp);
750    //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error
751    if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) {
752        return -1;
753    }
754
755    //From HWComposer
756    static const uint32_t DISPLAY_ATTRIBUTES[] = {
757        HWC_DISPLAY_VSYNC_PERIOD,
758        HWC_DISPLAY_WIDTH,
759        HWC_DISPLAY_HEIGHT,
760        HWC_DISPLAY_DPI_X,
761        HWC_DISPLAY_DPI_Y,
762        HWC_DISPLAY_NO_ATTRIBUTE,
763    };
764
765    const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
766            sizeof(DISPLAY_ATTRIBUTES)[0]);
767
768    for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
769        switch (attributes[i]) {
770        case HWC_DISPLAY_VSYNC_PERIOD:
771            values[i] = ctx->dpyAttr[disp].vsync_period;
772            break;
773        case HWC_DISPLAY_WIDTH:
774            values[i] = ctx->dpyAttr[disp].xres;
775            ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
776                    ctx->dpyAttr[disp].xres);
777            break;
778        case HWC_DISPLAY_HEIGHT:
779            values[i] = ctx->dpyAttr[disp].yres;
780            ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
781                    ctx->dpyAttr[disp].yres);
782            break;
783        case HWC_DISPLAY_DPI_X:
784            values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
785            break;
786        case HWC_DISPLAY_DPI_Y:
787            values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
788            break;
789        default:
790            ALOGE("Unknown display attribute %d",
791                    attributes[i]);
792            return -EINVAL;
793        }
794    }
795    return 0;
796}
797
798void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
799{
800    hwc_context_t* ctx = (hwc_context_t*)(dev);
801    Locker::Autolock _l(ctx->mDrawLock);
802    android::String8 aBuf("");
803    dumpsys_log(aBuf, "Qualcomm HWC state:\n");
804    dumpsys_log(aBuf, "  MDPVersion=%d\n", ctx->mMDP.version);
805    dumpsys_log(aBuf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
806    for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
807        if(ctx->mMDPComp[dpy])
808            ctx->mMDPComp[dpy]->dump(aBuf);
809    }
810    char ovDump[2048] = {'\0'};
811    ctx->mOverlay->getDump(ovDump, 2048);
812    dumpsys_log(aBuf, ovDump);
813    ovDump[0] = '\0';
814    ctx->mRotMgr->getDump(ovDump, 1024);
815    dumpsys_log(aBuf, ovDump);
816    ovDump[0] = '\0';
817    if(Writeback::getDump(ovDump, 1024)) {
818        dumpsys_log(aBuf, ovDump);
819        ovDump[0] = '\0';
820    }
821    strlcpy(buff, aBuf.string(), buff_len);
822}
823
824static int hwc_device_close(struct hw_device_t *dev)
825{
826    if(!dev) {
827        ALOGE("%s: NULL device pointer", __FUNCTION__);
828        return -1;
829    }
830    closeContext((hwc_context_t*)dev);
831    free(dev);
832
833    return 0;
834}
835
836static int hwc_device_open(const struct hw_module_t* module, const char* name,
837                           struct hw_device_t** device)
838{
839    int status = -EINVAL;
840
841    if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
842        struct hwc_context_t *dev;
843        dev = (hwc_context_t*)malloc(sizeof(*dev));
844        if(dev == NULL)
845            return status;
846        memset(dev, 0, sizeof(*dev));
847
848        //Initialize hwc context
849        initContext(dev);
850
851        //Setup HWC methods
852        dev->device.common.tag          = HARDWARE_DEVICE_TAG;
853        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_3;
854        dev->device.common.module       = const_cast<hw_module_t*>(module);
855        dev->device.common.close        = hwc_device_close;
856        dev->device.prepare             = hwc_prepare;
857        dev->device.set                 = hwc_set;
858        dev->device.eventControl        = hwc_eventControl;
859        dev->device.blank               = hwc_blank;
860        dev->device.query               = hwc_query;
861        dev->device.registerProcs       = hwc_registerProcs;
862        dev->device.dump                = hwc_dump;
863        dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;
864        dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
865        *device = &dev->device.common;
866        status = 0;
867    }
868    return status;
869}
870