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