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