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