hwc.cpp revision 3aaa003801643146fe86e91364c5ad9493ad40d7
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    /* No point to calling overlay_set on MDP3 */
142    if(list->flags & HWC_GEOMETRY_CHANGED &&
143            ctx->mMDP.version >= qdutils::MDP_V4_0) {
144        ctx->mOverlay->forceSet(dpy);
145    }
146}
147
148static int hwc_prepare_primary(hwc_composer_device_1 *dev,
149        hwc_display_contents_1_t *list) {
150    ATRACE_CALL();
151    hwc_context_t* ctx = (hwc_context_t*)(dev);
152    const int dpy = HWC_DISPLAY_PRIMARY;
153    if (LIKELY(list && list->numHwLayers > 1) &&
154            ctx->dpyAttr[dpy].isActive) {
155        reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
156        handleGeomChange(ctx, dpy, list);
157        uint32_t last = list->numHwLayers - 1;
158        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
159        if(fbLayer->handle) {
160            setListStats(ctx, list, dpy);
161#ifdef VPU_TARGET
162            ctx->mVPUClient->prepare(ctx, list);
163#endif
164            if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
165                const int fbZ = 0;
166                ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
167            }
168            if (ctx->mMDP.version < qdutils::MDP_V4_0) {
169                if(ctx->mCopyBit[dpy])
170                    ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
171            }
172        }
173    }
174    return 0;
175}
176
177static int hwc_prepare_external(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_EXTERNAL;
182
183    if (LIKELY(list && list->numHwLayers > 1) &&
184            ctx->dpyAttr[dpy].isActive &&
185            ctx->dpyAttr[dpy].connected) {
186        reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
187        handleGeomChange(ctx, dpy, list);
188        uint32_t last = list->numHwLayers - 1;
189        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
190        if(!ctx->dpyAttr[dpy].isPause) {
191            if(fbLayer->handle) {
192                ctx->dpyAttr[dpy].isConfiguring = false;
193                setListStats(ctx, list, dpy);
194                if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
195                    const int fbZ = 0;
196                    ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
197                }
198
199                if(ctx->listStats[dpy].isDisplayAnimating) {
200                    // Mark all app layers as HWC_OVERLAY for external during
201                    // animation, so that SF doesnt draw it on FB
202                    for(int i = 0 ;i < ctx->listStats[dpy].numAppLayers; i++) {
203                        hwc_layer_1_t *layer = &list->hwLayers[i];
204                        layer->compositionType = HWC_OVERLAY;
205                    }
206                }
207            }
208        } else {
209            // External Display is in Pause state.
210            // ToDo:
211            // Mark all application layers as OVERLAY so that
212            // GPU will not compose. This is done for power
213            // optimization
214        }
215    }
216    return 0;
217}
218
219static int hwc_prepare_virtual(hwc_composer_device_1 *dev,
220        hwc_display_contents_1_t *list) {
221    ATRACE_CALL();
222
223    hwc_context_t* ctx = (hwc_context_t*)(dev);
224    const int dpy = HWC_DISPLAY_VIRTUAL;
225
226    if (LIKELY(list && list->numHwLayers > 1) &&
227            ctx->dpyAttr[dpy].isActive &&
228            ctx->dpyAttr[dpy].connected) {
229        reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
230        handleGeomChange(ctx, dpy, list);
231        uint32_t last = list->numHwLayers - 1;
232        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
233        if(!ctx->dpyAttr[dpy].isPause) {
234            if(fbLayer->handle) {
235                ctx->dpyAttr[dpy].isConfiguring = false;
236                setListStats(ctx, list, dpy);
237                if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
238                    const int fbZ = 0;
239                    ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
240                }
241
242                if(ctx->listStats[dpy].isDisplayAnimating) {
243                    // Mark all app layers as HWC_OVERLAY for virtual during
244                    // animation, so that SF doesnt draw it on FB
245                    for(int i = 0 ;i < ctx->listStats[dpy].numAppLayers; i++) {
246                        hwc_layer_1_t *layer = &list->hwLayers[i];
247                        layer->compositionType = HWC_OVERLAY;
248                    }
249                }
250            }
251        } else {
252            // Virtual Display is in Pause state.
253            // ToDo:
254            // Mark all application layers as OVERLAY so that
255            // GPU will not compose. This is done for power
256            // optimization
257        }
258    }
259    return 0;
260}
261
262
263static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
264                       hwc_display_contents_1_t** displays)
265{
266    int ret = 0;
267    hwc_context_t* ctx = (hwc_context_t*)(dev);
268    //Will be unlocked at the end of set
269    ctx->mDrawLock.lock();
270    reset(ctx, numDisplays, displays);
271
272    ctx->mOverlay->configBegin();
273    ctx->mRotMgr->configBegin();
274    overlay::Writeback::configBegin();
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    case HWC_FORMAT_RB_SWAP:
450        value[0] = 1;
451        break;
452    default:
453        return -EINVAL;
454    }
455    return 0;
456
457}
458
459
460static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
461    ATRACE_CALL();
462    int ret = 0;
463    const int dpy = HWC_DISPLAY_PRIMARY;
464    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) {
465        uint32_t last = list->numHwLayers - 1;
466        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
467        int fd = -1; //FenceFD from the Copybit(valid in async mode)
468        bool copybitDone = false;
469        if(ctx->mCopyBit[dpy])
470            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
471        if(list->numHwLayers > 1)
472            hwc_sync(ctx, list, dpy, fd);
473
474        // Dump the layers for primary
475        if(ctx->mHwcDebug[dpy])
476            ctx->mHwcDebug[dpy]->dumpLayers(list);
477
478        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
479            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
480            ret = -1;
481        }
482#ifdef VPU_TARGET
483        ctx->mVPUClient->draw(ctx, list);
484#endif
485
486        //TODO We dont check for SKIP flag on this layer because we need PAN
487        //always. Last layer is always FB
488        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
489        if(copybitDone) {
490            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
491        }
492
493        if(hnd) {
494            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
495                ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
496                ret = -1;
497            }
498        }
499
500        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd,
501                                            ctx->listStats[dpy].roi)) {
502            ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
503            ret = -1;
504        }
505    }
506
507    closeAcquireFds(list);
508    return ret;
509}
510
511static int hwc_set_external(hwc_context_t *ctx,
512                            hwc_display_contents_1_t* list)
513{
514    ATRACE_CALL();
515    int ret = 0;
516
517    const int dpy = HWC_DISPLAY_EXTERNAL;
518
519
520    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
521        ctx->dpyAttr[dpy].connected &&
522        !ctx->dpyAttr[dpy].isPause) {
523        uint32_t last = list->numHwLayers - 1;
524        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
525        int fd = -1; //FenceFD from the Copybit(valid in async mode)
526        bool copybitDone = false;
527        if(ctx->mCopyBit[dpy])
528            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
529
530        if(list->numHwLayers > 1)
531            hwc_sync(ctx, list, dpy, fd);
532
533        // Dump the layers for external
534        if(ctx->mHwcDebug[dpy])
535            ctx->mHwcDebug[dpy]->dumpLayers(list);
536
537        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
538            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
539            ret = -1;
540        }
541
542        int extOnlyLayerIndex =
543                ctx->listStats[dpy].extOnlyLayerIndex;
544
545        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
546        if(extOnlyLayerIndex!= -1) {
547            hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
548            hnd = (private_handle_t *)extLayer->handle;
549        } else if(copybitDone) {
550            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
551        }
552
553        if(hnd && !isYuvBuffer(hnd)) {
554            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
555                ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
556                ret = -1;
557            }
558        }
559
560        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
561            ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
562            ret = -1;
563        }
564    }
565
566    closeAcquireFds(list);
567    return ret;
568}
569
570static int hwc_set_virtual(hwc_context_t *ctx,
571                            hwc_display_contents_1_t* list)
572{
573    ATRACE_CALL();
574    int ret = 0;
575
576    const int dpy = HWC_DISPLAY_VIRTUAL;
577
578
579    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
580            ctx->dpyAttr[dpy].connected &&
581            !ctx->dpyAttr[dpy].isPause) {
582        uint32_t last = list->numHwLayers - 1;
583        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
584        int fd = -1; //FenceFD from the Copybit(valid in async mode)
585        bool copybitDone = false;
586        if(ctx->mCopyBit[dpy])
587            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
588
589        if(list->numHwLayers > 1)
590            hwc_sync(ctx, list, dpy, fd);
591
592            // Dump the layers for virtual
593            if(ctx->mHwcDebug[dpy])
594                ctx->mHwcDebug[dpy]->dumpLayers(list);
595
596        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
597            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
598            ret = -1;
599        }
600
601        int extOnlyLayerIndex =
602            ctx->listStats[dpy].extOnlyLayerIndex;
603
604        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
605        if(extOnlyLayerIndex!= -1) {
606            hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
607            hnd = (private_handle_t *)extLayer->handle;
608        } else if(copybitDone) {
609            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
610        }
611
612        if(hnd && !isYuvBuffer(hnd)) {
613            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
614                ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
615                ret = -1;
616            }
617        }
618
619        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
620            ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
621            ret = -1;
622        }
623    }
624
625    closeAcquireFds(list);
626
627    if (list && !ctx->mVirtualonExtActive && (list->retireFenceFd < 0) ) {
628        // SF assumes HWC waits for the acquire fence and returns a new fence
629        // that signals when we're done. Since we don't wait, and also don't
630        // touch the buffer, we can just handle the acquire fence back to SF
631        // as the retire fence.
632        list->retireFenceFd = list->outbufAcquireFenceFd;
633    }
634
635    return ret;
636}
637
638
639static int hwc_set(hwc_composer_device_1 *dev,
640                   size_t numDisplays,
641                   hwc_display_contents_1_t** displays)
642{
643    int ret = 0;
644    hwc_context_t* ctx = (hwc_context_t*)(dev);
645    for (uint32_t i = 0; i <= numDisplays; i++) {
646        hwc_display_contents_1_t* list = displays[i];
647        int dpy = getDpyforExternalDisplay(ctx, i);
648        switch(dpy) {
649            case HWC_DISPLAY_PRIMARY:
650                ret = hwc_set_primary(ctx, list);
651                break;
652            case HWC_DISPLAY_EXTERNAL:
653                ret = hwc_set_external(ctx, list);
654                break;
655            case HWC_DISPLAY_VIRTUAL:
656                ret = hwc_set_virtual(ctx, list);
657                break;
658            default:
659                ret = -EINVAL;
660        }
661    }
662    // This is only indicative of how many times SurfaceFlinger posts
663    // frames to the display.
664    CALC_FPS();
665    MDPComp::resetIdleFallBack();
666    ctx->mVideoTransFlag = false;
667    if(ctx->mRotMgr->getNumActiveSessions() == 0)
668        Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
669    //Was locked at the beginning of prepare
670    ctx->mDrawLock.unlock();
671    return ret;
672}
673
674int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
675        uint32_t* configs, size_t* numConfigs) {
676    int ret = 0;
677    hwc_context_t* ctx = (hwc_context_t*)(dev);
678    disp = getDpyforExternalDisplay(ctx, disp);
679    //in 1.1 there is no way to choose a config, report as config id # 0
680    //This config is passed to getDisplayAttributes. Ignore for now.
681    switch(disp) {
682        case HWC_DISPLAY_PRIMARY:
683            if(*numConfigs > 0) {
684                configs[0] = 0;
685                *numConfigs = 1;
686            }
687            ret = 0; //NO_ERROR
688            break;
689        case HWC_DISPLAY_EXTERNAL:
690        case HWC_DISPLAY_VIRTUAL:
691            ret = -1; //Not connected
692            if(ctx->dpyAttr[disp].connected) {
693                ret = 0; //NO_ERROR
694                if(*numConfigs > 0) {
695                    configs[0] = 0;
696                    *numConfigs = 1;
697                }
698            }
699            break;
700    }
701    return ret;
702}
703
704int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
705        uint32_t config, const uint32_t* attributes, int32_t* values) {
706
707    hwc_context_t* ctx = (hwc_context_t*)(dev);
708    disp = getDpyforExternalDisplay(ctx, disp);
709    //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error
710    if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) {
711        return -1;
712    }
713
714    //From HWComposer
715    static const uint32_t DISPLAY_ATTRIBUTES[] = {
716        HWC_DISPLAY_VSYNC_PERIOD,
717        HWC_DISPLAY_WIDTH,
718        HWC_DISPLAY_HEIGHT,
719        HWC_DISPLAY_DPI_X,
720        HWC_DISPLAY_DPI_Y,
721        HWC_DISPLAY_NO_ATTRIBUTE,
722    };
723
724    const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
725            sizeof(DISPLAY_ATTRIBUTES)[0]);
726
727    for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
728        switch (attributes[i]) {
729        case HWC_DISPLAY_VSYNC_PERIOD:
730            values[i] = ctx->dpyAttr[disp].vsync_period;
731            break;
732        case HWC_DISPLAY_WIDTH:
733            values[i] = ctx->dpyAttr[disp].xres;
734            ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
735                    ctx->dpyAttr[disp].xres);
736            break;
737        case HWC_DISPLAY_HEIGHT:
738            values[i] = ctx->dpyAttr[disp].yres;
739            ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
740                    ctx->dpyAttr[disp].yres);
741            break;
742        case HWC_DISPLAY_DPI_X:
743            values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
744            break;
745        case HWC_DISPLAY_DPI_Y:
746            values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
747            break;
748        default:
749            ALOGE("Unknown display attribute %d",
750                    attributes[i]);
751            return -EINVAL;
752        }
753    }
754    return 0;
755}
756
757void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
758{
759    hwc_context_t* ctx = (hwc_context_t*)(dev);
760    Locker::Autolock _l(ctx->mDrawLock);
761    android::String8 aBuf("");
762    dumpsys_log(aBuf, "Qualcomm HWC state:\n");
763    dumpsys_log(aBuf, "  MDPVersion=%d\n", ctx->mMDP.version);
764    dumpsys_log(aBuf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
765    for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
766        if(ctx->mMDPComp[dpy])
767            ctx->mMDPComp[dpy]->dump(aBuf);
768    }
769    char ovDump[2048] = {'\0'};
770    ctx->mOverlay->getDump(ovDump, 2048);
771    dumpsys_log(aBuf, ovDump);
772    ovDump[0] = '\0';
773    ctx->mRotMgr->getDump(ovDump, 1024);
774    dumpsys_log(aBuf, ovDump);
775    ovDump[0] = '\0';
776    Writeback::getInstance()->getDump(ovDump, 1024);
777    dumpsys_log(aBuf, ovDump);
778    strlcpy(buff, aBuf.string(), buff_len);
779}
780
781static int hwc_device_close(struct hw_device_t *dev)
782{
783    if(!dev) {
784        ALOGE("%s: NULL device pointer", __FUNCTION__);
785        return -1;
786    }
787    closeContext((hwc_context_t*)dev);
788    free(dev);
789
790    return 0;
791}
792
793static int hwc_device_open(const struct hw_module_t* module, const char* name,
794                           struct hw_device_t** device)
795{
796    int status = -EINVAL;
797
798    if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
799        struct hwc_context_t *dev;
800        dev = (hwc_context_t*)malloc(sizeof(*dev));
801        memset(dev, 0, sizeof(*dev));
802
803        //Initialize hwc context
804        initContext(dev);
805
806        //Setup HWC methods
807        dev->device.common.tag          = HARDWARE_DEVICE_TAG;
808        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_2;
809        dev->device.common.module       = const_cast<hw_module_t*>(module);
810        dev->device.common.close        = hwc_device_close;
811        dev->device.prepare             = hwc_prepare;
812        dev->device.set                 = hwc_set;
813        dev->device.eventControl        = hwc_eventControl;
814        dev->device.blank               = hwc_blank;
815        dev->device.query               = hwc_query;
816        dev->device.registerProcs       = hwc_registerProcs;
817        dev->device.dump                = hwc_dump;
818        dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;
819        dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
820        *device = &dev->device.common;
821        status = 0;
822    }
823    return status;
824}
825