• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  * Copyright (C) 2012-2015, 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 "hdmi.h"
38 #include "hwc_copybit.h"
39 #include "hwc_ad.h"
40 #include "profiler.h"
41 #include "hwc_virtual.h"
42 
43 using namespace qhwc;
44 using namespace overlay;
45 
46 #define VSYNC_DEBUG 0
47 #define POWER_MODE_DEBUG 1
48 
49 static int hwc_device_open(const struct hw_module_t* module,
50                            const char* name,
51                            struct hw_device_t** device);
52 
53 static struct hw_module_methods_t hwc_module_methods = {
54     open: hwc_device_open
55 };
56 
57 static void reset_panel(struct hwc_composer_device_1* dev);
58 
59 hwc_module_t HAL_MODULE_INFO_SYM = {
60     common: {
61         tag: HARDWARE_MODULE_TAG,
62         version_major: 2,
63         version_minor: 0,
64         id: HWC_HARDWARE_MODULE_ID,
65         name: "Qualcomm Hardware Composer Module",
66         author: "CodeAurora Forum",
67         methods: &hwc_module_methods,
68         dso: 0,
69         reserved: {0},
70     }
71 };
72 
73 /*
74  * Save callback functions registered to HWC
75  */
hwc_registerProcs(struct hwc_composer_device_1 * dev,hwc_procs_t const * procs)76 static void hwc_registerProcs(struct hwc_composer_device_1* dev,
77                               hwc_procs_t const* procs)
78 {
79     ALOGI("%s", __FUNCTION__);
80     hwc_context_t* ctx = (hwc_context_t*)(dev);
81     if(!ctx) {
82         ALOGE("%s: Invalid context", __FUNCTION__);
83         return;
84     }
85     ctx->proc = procs;
86 
87     // Now that we have the functions needed, kick off
88     // the uevent & vsync threads
89     init_uevent_thread(ctx);
90     init_vsync_thread(ctx);
91 }
92 
setPaddingRound(hwc_context_t * ctx,int numDisplays,hwc_display_contents_1_t ** displays)93 static void setPaddingRound(hwc_context_t *ctx, int numDisplays,
94                             hwc_display_contents_1_t** displays) {
95     ctx->isPaddingRound = false;
96     for(int i = 0; i < numDisplays; i++) {
97         hwc_display_contents_1_t *list = displays[i];
98         if (LIKELY(list && list->numHwLayers > 0)) {
99             if((ctx->mPrevHwLayerCount[i] == 1 or
100                 ctx->mPrevHwLayerCount[i] == 0) and
101                (list->numHwLayers > 1)) {
102                 /* If the previous cycle for dpy 'i' has 0 AppLayers and the
103                  * current cycle has atleast 1 AppLayer, padding round needs
104                  * to be invoked in current cycle on all the active displays
105                  * to free up the resources.
106                  */
107                 ctx->isPaddingRound = true;
108             }
109             ctx->mPrevHwLayerCount[i] = (int)list->numHwLayers;
110         } else {
111             ctx->mPrevHwLayerCount[i] = 0;
112         }
113     }
114 }
115 
116 /* Based on certain conditions, isDMAStateChanging will be set
117  * to make this function self-contained */
setDMAState(hwc_context_t * ctx,int numDisplays,hwc_display_contents_1_t ** displays)118 static void setDMAState(hwc_context_t *ctx, int numDisplays,
119                         hwc_display_contents_1_t** displays) {
120 
121     ctx->isDMAStateChanging = false;
122     if(ctx->mRotMgr->getNumActiveSessions() == 0)
123         Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
124 
125     for(int dpy = 0; dpy < numDisplays; dpy++) {
126         hwc_display_contents_1_t *list = displays[dpy];
127         if (LIKELY(list && list->numHwLayers > 0)) {
128             for(size_t layerIndex = 0; layerIndex < list->numHwLayers;
129                                                   layerIndex++) {
130                 if(list->hwLayers[layerIndex].compositionType !=
131                                             HWC_FRAMEBUFFER_TARGET)
132                 {
133                     hwc_layer_1_t const* layer = &list->hwLayers[layerIndex];
134                     private_handle_t *hnd = (private_handle_t *)layer->handle;
135 
136                     /* If a layer requires rotation, set the DMA state
137                      * to BLOCK_MODE */
138 
139                     if (canUseRotator(ctx, dpy) &&
140                         (has90Transform(layer) || getRotDownscale(ctx, layer))
141                         && isRotationDoable(ctx, hnd)) {
142                         if(not (ctx->mOverlay->isDMAMultiplexingSupported() &&
143                                           dpy)) {
144                             if(ctx->mOverlay->isPipeTypeAttached(
145                                              overlay::utils::OV_MDP_PIPE_DMA))
146                                 ctx->isDMAStateChanging = true;
147                         }
148                         Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
149                     }
150                 }
151             }
152             if(dpy) {
153                 /* Uncomment the below code for testing purpose.
154                    Assuming the orientation value is in terms of HAL_TRANSFORM,
155                    this needs mapping to HAL, if its in different convention */
156 
157                 /* char value[PROPERTY_VALUE_MAX];
158                    property_get("sys.ext_orientation", value, "0");
159                    ctx->mExtOrientation = atoi(value);*/
160 
161                 if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
162                     if(ctx->mOverlay->isPipeTypeAttached(
163                                          overlay::utils::OV_MDP_PIPE_DMA)) {
164                         ctx->isDMAStateChanging = true;
165                     }
166                     Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
167                 }
168             }
169         }
170     }
171 }
172 
setNumActiveDisplays(hwc_context_t * ctx,int numDisplays,hwc_display_contents_1_t ** displays)173 static void setNumActiveDisplays(hwc_context_t *ctx, int numDisplays,
174                             hwc_display_contents_1_t** displays) {
175 
176     ctx->numActiveDisplays = 0;
177     for(int i = 0; i < numDisplays; i++) {
178         hwc_display_contents_1_t *list = displays[i];
179         if (LIKELY(list && list->numHwLayers > 0)) {
180             /* For display devices like SSD and screenrecord, we cannot
181              * rely on isActive and connected attributes of dpyAttr to
182              * determine if the displaydevice is active. Hence in case if
183              * the layer-list is non-null and numHwLayers > 0, we assume
184              * the display device to be active.
185              */
186             ctx->numActiveDisplays += 1;
187         }
188     }
189 }
190 
isHotPluggable(hwc_context_t * ctx,int dpy)191 static bool isHotPluggable(hwc_context_t *ctx, int dpy) {
192     return ((dpy == HWC_DISPLAY_EXTERNAL) ||
193             ((dpy == HWC_DISPLAY_PRIMARY) &&
194              ctx->mHDMIDisplay->isHDMIPrimaryDisplay()));
195 }
196 
reset(hwc_context_t * ctx,int numDisplays,hwc_display_contents_1_t ** displays)197 static void reset(hwc_context_t *ctx, int numDisplays,
198                   hwc_display_contents_1_t** displays) {
199 
200 
201     for(int i = 0; i < numDisplays; i++) {
202         hwc_display_contents_1_t *list = displays[i];
203         // XXX:SurfaceFlinger no longer guarantees that this
204         // value is reset on every prepare. However, for the layer
205         // cache we need to reset it.
206         // We can probably rethink that later on
207         if (LIKELY(list && list->numHwLayers > 0)) {
208             for(size_t j = 0; j < list->numHwLayers; j++) {
209                 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
210                     list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
211             }
212 
213         }
214 
215         if(ctx->mMDPComp[i])
216             ctx->mMDPComp[i]->reset();
217         if(ctx->mFBUpdate[i])
218             ctx->mFBUpdate[i]->reset();
219         if(ctx->mCopyBit[i])
220             ctx->mCopyBit[i]->reset();
221         if(ctx->mLayerRotMap[i])
222             ctx->mLayerRotMap[i]->reset();
223     }
224 
225     ctx->mAD->reset();
226 
227 }
228 
scaleDisplayFrame(hwc_context_t * ctx,int dpy,hwc_display_contents_1_t * list)229 static void scaleDisplayFrame(hwc_context_t *ctx, int dpy,
230                             hwc_display_contents_1_t *list) {
231     uint32_t origXres = ctx->dpyAttr[dpy].xres;
232     uint32_t origYres = ctx->dpyAttr[dpy].yres;
233     uint32_t newXres = ctx->dpyAttr[dpy].xres_new;
234     uint32_t newYres = ctx->dpyAttr[dpy].yres_new;
235     float xresRatio = (float)origXres / (float)newXres;
236     float yresRatio = (float)origYres / (float)newYres;
237     for (size_t i = 0; i < list->numHwLayers; i++) {
238         hwc_layer_1_t *layer = &list->hwLayers[i];
239         hwc_rect_t& displayFrame = layer->displayFrame;
240         hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
241         uint32_t layerWidth = displayFrame.right - displayFrame.left;
242         uint32_t layerHeight = displayFrame.bottom - displayFrame.top;
243         displayFrame.left = (int)(xresRatio * (float)displayFrame.left);
244         displayFrame.top = (int)(yresRatio * (float)displayFrame.top);
245         displayFrame.right = (int)((float)displayFrame.left +
246                                    (float)layerWidth * xresRatio);
247         displayFrame.bottom = (int)((float)displayFrame.top +
248                                     (float)layerHeight * yresRatio);
249     }
250 }
251 
hwc_prepare_primary(hwc_composer_device_1 * dev,hwc_display_contents_1_t * list)252 static int hwc_prepare_primary(hwc_composer_device_1 *dev,
253         hwc_display_contents_1_t *list) {
254     ATRACE_CALL();
255     hwc_context_t* ctx = (hwc_context_t*)(dev);
256     const int dpy = HWC_DISPLAY_PRIMARY;
257     bool fbComp = false;
258     if (!ctx->mDefaultModeApplied)
259         applyDefaultMode(ctx);
260     if (LIKELY(list && list->numHwLayers > 1) && ctx->dpyAttr[dpy].connected &&
261             (ctx->dpyAttr[dpy].isActive ||
262              ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
263             && !ctx->dpyAttr[dpy].isPause) {
264 
265         // When HDMI is primary we should rely on the first valid
266         // draw call in order to activate the display
267         if (!ctx->dpyAttr[dpy].isActive) {
268             // If the cable is connected after HWC initialization and before
269             // the UEvent thread is initialized then we will miss the ONLINE
270             // event. We need to update the display appropriately when we get
271             // the first valid frame.
272             int cableConnected = ctx->mHDMIDisplay->getConnectedState();
273             if ((cableConnected == 1) && !ctx->dpyAttr[dpy].connected) {
274                 qhwc::handle_online(ctx, dpy);
275             }
276             ctx->mHDMIDisplay->activateDisplay();
277             ctx->dpyAttr[dpy].isActive = true;
278         }
279 
280         if (ctx->dpyAttr[dpy].customFBSize &&
281                 list->flags & HWC_GEOMETRY_CHANGED)
282             scaleDisplayFrame(ctx, dpy, list);
283 
284         reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
285         setListStats(ctx, list, dpy);
286 
287         fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
288 
289         if (fbComp) {
290             const int fbZ = 0;
291             if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) {
292                 ctx->mOverlay->clear(dpy);
293                 ctx->mLayerRotMap[dpy]->clear();
294             }
295         }
296 
297         if (ctx->mMDP.version < qdutils::MDP_V4_0) {
298             if(ctx->mCopyBit[dpy])
299                 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
300         }
301         setGPUHint(ctx, list);
302     }
303     return 0;
304 }
305 
hwc_prepare_external(hwc_composer_device_1 * dev,hwc_display_contents_1_t * list)306 static int hwc_prepare_external(hwc_composer_device_1 *dev,
307         hwc_display_contents_1_t *list) {
308     ATRACE_CALL();
309     hwc_context_t* ctx = (hwc_context_t*)(dev);
310     const int dpy = HWC_DISPLAY_EXTERNAL;
311 
312     if (LIKELY(list && list->numHwLayers > 1) &&
313             ctx->dpyAttr[dpy].isActive &&
314             ctx->dpyAttr[dpy].connected) {
315         reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
316         if(!ctx->dpyAttr[dpy].isPause) {
317             ctx->dpyAttr[dpy].isConfiguring = false;
318             setListStats(ctx, list, dpy);
319             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
320                 const int fbZ = 0;
321                 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
322                 {
323                     ctx->mOverlay->clear(dpy);
324                     ctx->mLayerRotMap[dpy]->clear();
325                 }
326             }
327         } else {
328             /* External Display is in Pause state.
329              * Mark all application layers as OVERLAY so that
330              * GPU will not compose.
331              */
332             for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
333                 hwc_layer_1_t *layer = &list->hwLayers[i];
334                 layer->compositionType = HWC_OVERLAY;
335             }
336         }
337     }
338     return 0;
339 }
340 
hwc_prepare(hwc_composer_device_1 * dev,size_t numDisplays,hwc_display_contents_1_t ** displays)341 static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
342                        hwc_display_contents_1_t** displays)
343 {
344     int ret = 0;
345     hwc_context_t* ctx = (hwc_context_t*)(dev);
346 
347     if (ctx->mPanelResetStatus) {
348         ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__);
349         reset_panel(dev);
350     }
351 
352     //Will be unlocked at the end of set
353     ctx->mDrawLock.lock();
354     setPaddingRound(ctx, (int)numDisplays, displays);
355     setDMAState(ctx, (int)numDisplays, displays);
356     setNumActiveDisplays(ctx, (int)numDisplays, displays);
357     reset(ctx, (int)numDisplays, displays);
358 
359     ctx->mOverlay->configBegin();
360     ctx->mRotMgr->configBegin();
361     overlay::Writeback::configBegin();
362 
363     for (int32_t dpy = ((int32_t)numDisplays-1); dpy >=0 ; dpy--) {
364         hwc_display_contents_1_t *list = displays[dpy];
365         resetROI(ctx, dpy);
366         switch(dpy) {
367             case HWC_DISPLAY_PRIMARY:
368                 ret = hwc_prepare_primary(dev, list);
369                 break;
370             case HWC_DISPLAY_EXTERNAL:
371                 ret = hwc_prepare_external(dev, list);
372                 break;
373             case HWC_DISPLAY_VIRTUAL:
374                 if(ctx->mHWCVirtual)
375                     ret = ctx->mHWCVirtual->prepare(dev, list);
376                 break;
377             default:
378                 ret = -EINVAL;
379         }
380     }
381 
382     ctx->mOverlay->configDone();
383     ctx->mRotMgr->configDone();
384     overlay::Writeback::configDone();
385     // If VD list is deleted, mdp overlay pipe objects and writeback object
386     // are deleted as part of configDone functions.
387     // Proceed with HWCVirtualVDS object deletion.
388     if(ctx->mHWCVirtual)
389         ctx->mHWCVirtual->destroy(ctx, numDisplays, displays);
390 
391     return ret;
392 }
393 
hwc_eventControl(struct hwc_composer_device_1 * dev,int dpy,int event,int enable)394 static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
395                              int event, int enable)
396 {
397     ATRACE_CALL();
398     int ret = 0;
399     hwc_context_t* ctx = (hwc_context_t*)(dev);
400     switch(event) {
401         case HWC_EVENT_VSYNC:
402             if (ctx->vstate.enable == enable)
403                 break;
404             ret = hwc_vsync_control(ctx, dpy, enable);
405             if(ret == 0)
406                 ctx->vstate.enable = !!enable;
407             ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s",
408                       (enable)?"ENABLED":"DISABLED");
409             break;
410 #ifdef QCOM_BSP
411         case  HWC_EVENT_ORIENTATION:
412             if(dpy == HWC_DISPLAY_PRIMARY) {
413                 Locker::Autolock _l(ctx->mDrawLock);
414                 // store the primary display orientation
415                 ctx->deviceOrientation = enable;
416             }
417             break;
418 #endif
419         default:
420             ret = -EINVAL;
421     }
422     return ret;
423 }
424 
hwc_setPowerMode(struct hwc_composer_device_1 * dev,int dpy,int mode)425 static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
426         int mode)
427 {
428     ATRACE_CALL();
429     hwc_context_t* ctx = (hwc_context_t*)(dev);
430     int ret = 0, value = 0;
431 
432     Locker::Autolock _l(ctx->mDrawLock);
433     ALOGD_IF(POWER_MODE_DEBUG, "%s: Setting mode %d on display: %d",
434             __FUNCTION__, mode, dpy);
435 
436     switch(mode) {
437         case HWC_POWER_MODE_OFF:
438             // free up all the overlay pipes in use
439             // when we get a blank for either display
440             // makes sure that all pipes are freed
441             ctx->mOverlay->configBegin();
442             ctx->mOverlay->configDone();
443             ctx->mRotMgr->clear();
444             // If VDS is connected, do not clear WB object as it
445             // will end up detaching IOMMU. This is required
446             // to send black frame to WFD sink on power suspend.
447             // Note: With this change, we keep the WriteBack object
448             // alive on power suspend for AD use case.
449             value = FB_BLANK_POWERDOWN;
450             break;
451         case HWC_POWER_MODE_DOZE:
452         case HWC_POWER_MODE_DOZE_SUSPEND:
453             value = FB_BLANK_VSYNC_SUSPEND;
454             break;
455         case HWC_POWER_MODE_NORMAL:
456             value = FB_BLANK_UNBLANK;
457             break;
458     }
459 
460     switch(dpy) {
461     case HWC_DISPLAY_PRIMARY:
462         if(ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
463             if(ctx->dpyAttr[dpy].connected) {
464                 // When HDMI is connected as primary we clean up resources
465                 // and call commit to generate a black frame on the interface.
466                 // However, we do not call blank since we need the timing
467                 // generator and HDMI core to remain turned on.
468                 if((mode == HWC_POWER_MODE_OFF) &&
469                         (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd))) {
470                     ALOGE("%s: display commit fail for %d", __FUNCTION__, dpy);
471                     ret = -1;
472                 }
473             }
474         } else {
475             if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) {
476                 ALOGE("%s: ioctl FBIOBLANK failed for Primary with error %s"
477                         " value %d", __FUNCTION__, strerror(errno), value);
478                 return -errno;
479             }
480 
481             if(mode == HWC_POWER_MODE_NORMAL && !ctx->mHPDEnabled) {
482                 // Enable HPD here, as during bootup POWER_MODE_NORMAL is set
483                 // when SF is completely initialized
484                 ctx->mHDMIDisplay->setHPD(1);
485                 ctx->mHPDEnabled = true;
486             }
487 
488             ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
489         }
490         //Deliberate fall through since there is no explicit power mode for
491         //virtual displays.
492     case HWC_DISPLAY_VIRTUAL:
493         if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
494             const int dpy = HWC_DISPLAY_VIRTUAL;
495             if(mode == HWC_POWER_MODE_OFF and
496                     (not ctx->dpyAttr[dpy].isPause)) {
497                 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
498                     ALOGE("%s: displayCommit failed for virtual", __FUNCTION__);
499                     ret = -1;
500                 }
501             }
502             ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
503         }
504         break;
505     case HWC_DISPLAY_EXTERNAL:
506         if(mode == HWC_POWER_MODE_OFF) {
507             if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
508                 ALOGE("%s: displayCommit failed for external", __FUNCTION__);
509                 ret = -1;
510             }
511         }
512         ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
513         break;
514     default:
515         return -EINVAL;
516     }
517 
518     ALOGD_IF(POWER_MODE_DEBUG, "%s: Done setting mode %d on display %d",
519             __FUNCTION__, mode, dpy);
520     return ret;
521 }
522 
reset_panel(struct hwc_composer_device_1 * dev)523 static void reset_panel(struct hwc_composer_device_1* dev)
524 {
525     int ret = 0;
526     hwc_context_t* ctx = (hwc_context_t*)(dev);
527 
528     if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
529         ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__);
530         ctx->mPanelResetStatus = false;
531         return;
532     }
533 
534     ALOGD("%s: setting power mode off", __FUNCTION__);
535     ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_OFF);
536     if (ret < 0) {
537         ALOGE("%s: FBIOBLANK failed to BLANK:  %s", __FUNCTION__,
538                 strerror(errno));
539     }
540 
541     ALOGD("%s: setting power mode normal and enabling vsync", __FUNCTION__);
542     ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL);
543     if (ret < 0) {
544         ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
545                 strerror(errno));
546     }
547     hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
548 
549     ctx->mPanelResetStatus = false;
550 }
551 
552 
hwc_query(struct hwc_composer_device_1 * dev,int param,int * value)553 static int hwc_query(struct hwc_composer_device_1* dev,
554                      int param, int* value)
555 {
556     hwc_context_t* ctx = (hwc_context_t*)(dev);
557     int supported = HWC_DISPLAY_PRIMARY_BIT;
558 
559     switch (param) {
560     case HWC_BACKGROUND_LAYER_SUPPORTED:
561         // Not supported for now
562         value[0] = 0;
563         break;
564     case HWC_DISPLAY_TYPES_SUPPORTED:
565         if(ctx->mMDP.hasOverlay) {
566             supported |= HWC_DISPLAY_VIRTUAL_BIT;
567             if(!(qdutils::MDPVersion::getInstance().is8x26() ||
568                         qdutils::MDPVersion::getInstance().is8x16() ||
569                         qdutils::MDPVersion::getInstance().is8x39()))
570                 supported |= HWC_DISPLAY_EXTERNAL_BIT;
571         }
572         value[0] = supported;
573         break;
574     case HWC_FORMAT_RB_SWAP:
575         value[0] = 1;
576         break;
577     case HWC_COLOR_FILL:
578         value[0] = 1;
579         break;
580     default:
581         return -EINVAL;
582     }
583     return 0;
584 
585 }
586 
587 
hwc_set_primary(hwc_context_t * ctx,hwc_display_contents_1_t * list)588 static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
589     ATRACE_CALL();
590     int ret = 0;
591     const int dpy = HWC_DISPLAY_PRIMARY;
592     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive
593             && !ctx->dpyAttr[dpy].isPause) {
594         size_t last = list->numHwLayers - 1;
595         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
596         int fd = -1; //FenceFD from the Copybit(valid in async mode)
597         bool copybitDone = false;
598 
599         if (ctx->mCopyBit[dpy]) {
600             if (ctx->mMDP.version < qdutils::MDP_V4_0)
601                 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
602             else
603                 fd = ctx->mMDPComp[dpy]->drawOverlap(ctx, list);
604         }
605 
606         if(list->numHwLayers > 1)
607             hwc_sync(ctx, list, dpy, fd);
608 
609         // Dump the layers for primary
610         if(ctx->mHwcDebug[dpy])
611             ctx->mHwcDebug[dpy]->dumpLayers(list);
612 
613         if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
614             ALOGE("%s: MDPComp draw failed", __FUNCTION__);
615             ret = -1;
616         }
617 
618         //TODO We dont check for SKIP flag on this layer because we need PAN
619         //always. Last layer is always FB
620         private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
621         if(copybitDone && ctx->mMDP.version >= qdutils::MDP_V4_0) {
622             hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
623         }
624 
625         if(isAbcInUse(ctx) == true) {
626             int index = ctx->listStats[dpy].renderBufIndexforABC;
627             hwc_layer_1_t *tempLayer = &list->hwLayers[index];
628             hnd = (private_handle_t *)tempLayer->handle;
629         }
630 
631         if(hnd) {
632             if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
633                 ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
634                 ret = -1;
635             }
636         }
637 
638         /* When source split is enabled, right ROI will always be NULL since the
639          * ROI for the whole panel generated in a single coordinate system will
640          * be populuated in left ROI. So leave the right ROI untouched */
641         int lSplit = qdutils::MDPVersion::getInstance().isSrcSplit() ? 0 :
642                     (isDisplaySplit(ctx, dpy) ? getLeftSplit(ctx, dpy) : 0);
643         qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim(
644             ctx->listStats[dpy].lRoi.left,
645             ctx->listStats[dpy].lRoi.top,
646             ctx->listStats[dpy].lRoi.right - ctx->listStats[dpy].lRoi.left,
647             ctx->listStats[dpy].lRoi.bottom - ctx->listStats[dpy].lRoi.top);
648 
649         qhwc::ovutils::Dim rRoi = qhwc::ovutils::Dim(
650             ctx->listStats[dpy].rRoi.left - lSplit,
651             ctx->listStats[dpy].rRoi.top,
652             ctx->listStats[dpy].rRoi.right - ctx->listStats[dpy].rRoi.left,
653             ctx->listStats[dpy].rRoi.bottom - ctx->listStats[dpy].rRoi.top);
654 
655         if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, lRoi, rRoi)) {
656             ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
657             ret = -1;
658         }
659 
660     }
661 
662     closeAcquireFds(list);
663     return ret;
664 }
665 
hwc_set_external(hwc_context_t * ctx,hwc_display_contents_1_t * list)666 static int hwc_set_external(hwc_context_t *ctx,
667                             hwc_display_contents_1_t* list)
668 {
669     ATRACE_CALL();
670     int ret = 0;
671 
672     const int dpy = HWC_DISPLAY_EXTERNAL;
673 
674 
675     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
676         ctx->dpyAttr[dpy].connected &&
677         !ctx->dpyAttr[dpy].isPause) {
678         size_t last = list->numHwLayers - 1;
679         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
680         int fd = -1; //FenceFD from the Copybit(valid in async mode)
681         bool copybitDone = false;
682         if(ctx->mCopyBit[dpy])
683             copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
684 
685         if(list->numHwLayers > 1)
686             hwc_sync(ctx, list, dpy, fd);
687 
688         // Dump the layers for external
689         if(ctx->mHwcDebug[dpy])
690             ctx->mHwcDebug[dpy]->dumpLayers(list);
691 
692         if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
693             ALOGE("%s: MDPComp draw failed", __FUNCTION__);
694             ret = -1;
695         }
696 
697         private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
698         if(copybitDone) {
699             hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
700         }
701 
702         if(hnd) {
703             if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
704                 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
705                 ret = -1;
706             }
707         }
708 
709         if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
710             ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
711             ret = -1;
712         }
713     }
714 
715     closeAcquireFds(list);
716     return ret;
717 }
718 
hwc_set(hwc_composer_device_1 * dev,size_t numDisplays,hwc_display_contents_1_t ** displays)719 static int hwc_set(hwc_composer_device_1 *dev,
720                    size_t numDisplays,
721                    hwc_display_contents_1_t** displays)
722 {
723     int ret = 0;
724     hwc_context_t* ctx = (hwc_context_t*)(dev);
725     for (int dpy = 0; dpy < (int)numDisplays; dpy++) {
726         hwc_display_contents_1_t* list = displays[dpy];
727         switch(dpy) {
728             case HWC_DISPLAY_PRIMARY:
729                 ret = hwc_set_primary(ctx, list);
730                 break;
731             case HWC_DISPLAY_EXTERNAL:
732                 ret = hwc_set_external(ctx, list);
733                 break;
734             case HWC_DISPLAY_VIRTUAL:
735                 if(ctx->mHWCVirtual)
736                     ret = ctx->mHWCVirtual->set(ctx, list);
737                 break;
738             default:
739                 ret = -EINVAL;
740         }
741     }
742     // This is only indicative of how many times SurfaceFlinger posts
743     // frames to the display.
744     CALC_FPS();
745     MDPComp::resetIdleFallBack();
746     ctx->mVideoTransFlag = false;
747     //Was locked at the beginning of prepare
748     ctx->mDrawLock.unlock();
749     return ret;
750 }
751 
hwc_getDisplayConfigs(struct hwc_composer_device_1 * dev,int disp,uint32_t * configs,size_t * numConfigs)752 int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
753         uint32_t* configs, size_t* numConfigs) {
754     hwc_context_t* ctx = (hwc_context_t*)(dev);
755 
756     Locker::Autolock _l(ctx->mDrawLock);
757     bool hotPluggable = isHotPluggable(ctx, disp);
758     bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
759     // If hotpluggable or virtual displays are inactive return error
760     if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
761         ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
762         return -EINVAL;
763     }
764 
765     if (*numConfigs <= 0) {
766         ALOGE("%s Invalid number of configs (%d)", __FUNCTION__, *numConfigs);
767         return -EINVAL;
768     }
769 
770     switch(disp) {
771         case HWC_DISPLAY_PRIMARY:
772             if (hotPluggable) {
773                 ctx->mHDMIDisplay->getDisplayConfigs(configs, numConfigs);
774             } else {
775                 if(ctx->mColorMode->getNumModes() > 0) {
776                     *numConfigs = ctx->mColorMode->getNumModes();
777                     for (size_t i = 0; i < *numConfigs; i++)
778                         configs[i] = (uint32_t) i;
779 
780                 } else {
781                     configs[0] = 0;
782                     *numConfigs = 1;
783                 }
784             }
785             break;
786         case HWC_DISPLAY_EXTERNAL:
787                 ctx->mHDMIDisplay->getDisplayConfigs(configs, numConfigs);
788             break;
789         case HWC_DISPLAY_VIRTUAL:
790             configs[0] = 0;
791             *numConfigs = 1;
792             break;
793     }
794     return 0;
795 }
796 
hwc_getDisplayAttributes(struct hwc_composer_device_1 * dev,int disp,uint32_t config,const uint32_t * attributes,int32_t * values)797 int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
798         uint32_t config, const uint32_t* attributes, int32_t* values) {
799 
800     hwc_context_t* ctx = (hwc_context_t*)(dev);
801 
802     Locker::Autolock _l(ctx->mDrawLock);
803     bool hotPluggable = isHotPluggable(ctx, disp);
804     bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
805     // If hotpluggable or virtual displays are inactive return error
806     if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
807         ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
808         return -EINVAL;
809     }
810 
811     uint32_t xres = 0, yres = 0, refresh = 0;
812     int ret = 0;
813     if (hotPluggable) {
814         ret = ctx->mHDMIDisplay->getAttrForConfig(config, xres, yres, refresh);
815         if(ret < 0) {
816             ALOGE("%s Error getting attributes for config %d",
817                     __FUNCTION__, config);
818             return ret;
819         }
820     }
821 
822     for (size_t i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
823         switch (attributes[i]) {
824         case HWC_DISPLAY_VSYNC_PERIOD:
825             values[i] =
826                     hotPluggable ? refresh : ctx->dpyAttr[disp].vsync_period;
827             break;
828         case HWC_DISPLAY_WIDTH:
829             if (ctx->dpyAttr[disp].customFBSize)
830                 values[i] = ctx->dpyAttr[disp].xres_new;
831             else
832                 values[i] = hotPluggable ? xres : ctx->dpyAttr[disp].xres;
833 
834             ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
835                     values[i]);
836             break;
837         case HWC_DISPLAY_HEIGHT:
838             if (ctx->dpyAttr[disp].customFBSize)
839                 values[i] = ctx->dpyAttr[disp].yres_new;
840             else
841                 values[i] = hotPluggable ? yres : ctx->dpyAttr[disp].yres;
842             ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
843                     values[i]);
844             break;
845         case HWC_DISPLAY_DPI_X:
846             values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
847             break;
848         case HWC_DISPLAY_DPI_Y:
849             values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
850             break;
851         case HWC_DISPLAY_COLOR_TRANSFORM:
852             values[i] = ctx->mColorMode->getModeForIndex(config);
853             break;
854         default:
855             ALOGE("Unknown display attribute %d",
856                     attributes[i]);
857             return -EINVAL;
858         }
859     }
860     return 0;
861 }
862 
hwc_dump(struct hwc_composer_device_1 * dev,char * buff,int buff_len)863 void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
864 {
865     hwc_context_t* ctx = (hwc_context_t*)(dev);
866     Locker::Autolock _l(ctx->mDrawLock);
867     android::String8 aBuf("");
868     dumpsys_log(aBuf, "Qualcomm HWC state:\n");
869     dumpsys_log(aBuf, "  MDPVersion=%d\n", ctx->mMDP.version);
870     dumpsys_log(aBuf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
871     dumpsys_log(aBuf, "  DynRefreshRate=%d\n",
872                 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].dynRefreshRate);
873     for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
874         if(ctx->mMDPComp[dpy])
875             ctx->mMDPComp[dpy]->dump(aBuf, ctx);
876     }
877     char ovDump[2048] = {'\0'};
878     ctx->mOverlay->getDump(ovDump, 2048);
879     dumpsys_log(aBuf, ovDump);
880     ovDump[0] = '\0';
881     ctx->mRotMgr->getDump(ovDump, 1024);
882     dumpsys_log(aBuf, ovDump);
883     ovDump[0] = '\0';
884     if(Writeback::getDump(ovDump, 1024)) {
885         dumpsys_log(aBuf, ovDump);
886         ovDump[0] = '\0';
887     }
888     strlcpy(buff, aBuf.string(), buff_len);
889 }
890 
hwc_getActiveConfig(struct hwc_composer_device_1 * dev,int disp)891 int hwc_getActiveConfig(struct hwc_composer_device_1* dev, int disp)
892 {
893     hwc_context_t* ctx = (hwc_context_t*)(dev);
894 
895     Locker::Autolock _l(ctx->mDrawLock);
896     bool hotPluggable = isHotPluggable(ctx, disp);
897     bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
898     // If hotpluggable or virtual displays are inactive return error
899     if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
900         ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
901         return -EINVAL;
902     }
903 
904     // For use cases when primary panel is the default interface we only have
905     // the default config (0th index)
906     if (!hotPluggable && HWC_DISPLAY_PRIMARY) {
907         return ctx->mColorMode->getActiveModeIndex();
908     } else if (isVirtualDisplay) {
909         return 0;
910     }
911 
912     return ctx->mHDMIDisplay->getActiveConfig();
913 }
914 
hwc_setActiveConfig(struct hwc_composer_device_1 * dev,int disp,int index)915 int hwc_setActiveConfig(struct hwc_composer_device_1* dev, int disp, int index)
916 {
917     hwc_context_t* ctx = (hwc_context_t*)(dev);
918 
919     Locker::Autolock _l(ctx->mDrawLock);
920     bool hotPluggable = isHotPluggable(ctx, disp);
921     bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
922     // If hotpluggable or virtual displays are inactive return error
923     if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
924         ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
925         return -EINVAL;
926     }
927 
928     // For use cases when primary panel is the default interface we only switch
929     // color modes
930     if(!hotPluggable && disp == HWC_DISPLAY_PRIMARY) {
931         return ctx->mColorMode->applyModeByIndex(index);
932     } else if (isVirtualDisplay) {
933         // virtual supports only the default config (0th index)
934         return (index == 0) ? index : -EINVAL;
935     }
936 
937     return ctx->mHDMIDisplay->setActiveConfig(index);
938 }
939 
hwc_device_close(struct hw_device_t * dev)940 static int hwc_device_close(struct hw_device_t *dev)
941 {
942     if(!dev) {
943         ALOGE("%s: NULL device pointer", __FUNCTION__);
944         return -1;
945     }
946     closeContext((hwc_context_t*)dev);
947     free(dev);
948 
949     return 0;
950 }
951 
hwc_device_open(const struct hw_module_t * module,const char * name,struct hw_device_t ** device)952 static int hwc_device_open(const struct hw_module_t* module, const char* name,
953                            struct hw_device_t** device)
954 {
955     int status = -EINVAL;
956 
957     if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
958         struct hwc_context_t *dev;
959         dev = (hwc_context_t*)malloc(sizeof(*dev));
960         if(dev == NULL)
961             return status;
962         memset(dev, 0, sizeof(*dev));
963 
964         //Initialize hwc context
965         initContext(dev);
966 
967         //Setup HWC methods
968         dev->device.common.tag          = HARDWARE_DEVICE_TAG;
969         dev->device.common.version      = HWC_DEVICE_API_VERSION_1_5;
970         dev->device.common.module       = const_cast<hw_module_t*>(module);
971         dev->device.common.close        = hwc_device_close;
972         dev->device.prepare             = hwc_prepare;
973         dev->device.set                 = hwc_set;
974         dev->device.eventControl        = hwc_eventControl;
975         dev->device.setPowerMode        = hwc_setPowerMode;
976         dev->device.query               = hwc_query;
977         dev->device.registerProcs       = hwc_registerProcs;
978         dev->device.dump                = hwc_dump;
979         dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;
980         dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
981         dev->device.getActiveConfig     = hwc_getActiveConfig;
982         dev->device.setActiveConfig     = hwc_setActiveConfig;
983         *device = &dev->device.common;
984         status = 0;
985     }
986     return status;
987 }
988