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_configure_color_temp(hwc_composer_device_1 * dev)252 static void hwc_configure_color_temp(hwc_composer_device_1* dev) {
253 hwc_context_t* ctx = (hwc_context_t*)(dev);
254 char value[PROPERTY_VALUE_MAX];
255 bool cool;
256
257 property_get("persist.sys.debug.color_temp", value, "x");
258 cool = (value[0] == '1');
259
260 if ((value[0] == '0' || value[0] == '1') &&
261 cool != ctx->mCoolColorTemperatureEnabled) {
262 ctx->mCoolColorTemperatureEnabled = cool;
263
264 ALOGI("Color temperature change. Cool = %d", cool ? 1 : 0);
265
266 int fd = open("/sys/class/graphics/fb0/color_temp", O_WRONLY);
267 if (fd >= 0) {
268 if (cool)
269 write(fd, "1", 2);
270 else
271 write(fd, "0", 2);
272 close(fd);
273 } else {
274 ALOGE("Failed to open color_temp file with result=%d", fd);
275 }
276 }
277 }
278
279
hwc_prepare_primary(hwc_composer_device_1 * dev,hwc_display_contents_1_t * list)280 static int hwc_prepare_primary(hwc_composer_device_1 *dev,
281 hwc_display_contents_1_t *list) {
282 ATRACE_CALL();
283 hwc_context_t* ctx = (hwc_context_t*)(dev);
284 const int dpy = HWC_DISPLAY_PRIMARY;
285 bool fbComp = false;
286 if (!ctx->mDefaultModeApplied)
287 applyDefaultMode(ctx);
288 if (LIKELY(list && list->numHwLayers > 1) && ctx->dpyAttr[dpy].connected &&
289 (ctx->dpyAttr[dpy].isActive ||
290 ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
291 && !ctx->dpyAttr[dpy].isPause) {
292
293 // When HDMI is primary we should rely on the first valid
294 // draw call in order to activate the display
295 if (!ctx->dpyAttr[dpy].isActive) {
296 // If the cable is connected after HWC initialization and before
297 // the UEvent thread is initialized then we will miss the ONLINE
298 // event. We need to update the display appropriately when we get
299 // the first valid frame.
300 int cableConnected = ctx->mHDMIDisplay->getConnectedState();
301 if ((cableConnected == 1) && !ctx->dpyAttr[dpy].connected) {
302 qhwc::handle_online(ctx, dpy);
303 }
304 ctx->mHDMIDisplay->activateDisplay();
305 ctx->dpyAttr[dpy].isActive = true;
306 }
307
308 if (ctx->dpyAttr[dpy].customFBSize &&
309 list->flags & HWC_GEOMETRY_CHANGED)
310 scaleDisplayFrame(ctx, dpy, list);
311
312 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
313 setListStats(ctx, list, dpy);
314
315 fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
316
317 if (fbComp) {
318 const int fbZ = 0;
319 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) {
320 ctx->mOverlay->clear(dpy);
321 ctx->mLayerRotMap[dpy]->clear();
322 }
323 }
324
325 if (ctx->mMDP.version < qdutils::MDP_V4_0) {
326 if(ctx->mCopyBit[dpy])
327 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
328 }
329 setGPUHint(ctx, list);
330 }
331 return 0;
332 }
333
hwc_prepare_external(hwc_composer_device_1 * dev,hwc_display_contents_1_t * list)334 static int hwc_prepare_external(hwc_composer_device_1 *dev,
335 hwc_display_contents_1_t *list) {
336 ATRACE_CALL();
337 hwc_context_t* ctx = (hwc_context_t*)(dev);
338 const int dpy = HWC_DISPLAY_EXTERNAL;
339
340 if (LIKELY(list && list->numHwLayers > 1) &&
341 ctx->dpyAttr[dpy].isActive &&
342 ctx->dpyAttr[dpy].connected) {
343 reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
344 if(!ctx->dpyAttr[dpy].isPause) {
345 ctx->dpyAttr[dpy].isConfiguring = false;
346 setListStats(ctx, list, dpy);
347 if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
348 const int fbZ = 0;
349 if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
350 {
351 ctx->mOverlay->clear(dpy);
352 ctx->mLayerRotMap[dpy]->clear();
353 }
354 }
355 } else {
356 /* External Display is in Pause state.
357 * Mark all application layers as OVERLAY so that
358 * GPU will not compose.
359 */
360 for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
361 hwc_layer_1_t *layer = &list->hwLayers[i];
362 layer->compositionType = HWC_OVERLAY;
363 }
364 }
365 }
366 return 0;
367 }
368
hwc_prepare(hwc_composer_device_1 * dev,size_t numDisplays,hwc_display_contents_1_t ** displays)369 static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
370 hwc_display_contents_1_t** displays)
371 {
372 int ret = 0;
373 hwc_context_t* ctx = (hwc_context_t*)(dev);
374
375 if (ctx->mPanelResetStatus) {
376 ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__);
377 reset_panel(dev);
378 }
379
380 //Will be unlocked at the end of set
381 ctx->mDrawLock.lock();
382 setPaddingRound(ctx, (int)numDisplays, displays);
383 setDMAState(ctx, (int)numDisplays, displays);
384 setNumActiveDisplays(ctx, (int)numDisplays, displays);
385 reset(ctx, (int)numDisplays, displays);
386
387 ctx->mOverlay->configBegin();
388 ctx->mRotMgr->configBegin();
389 overlay::Writeback::configBegin();
390
391 for (int32_t dpy = ((int32_t)numDisplays-1); dpy >=0 ; dpy--) {
392 hwc_display_contents_1_t *list = displays[dpy];
393 resetROI(ctx, dpy);
394 switch(dpy) {
395 case HWC_DISPLAY_PRIMARY:
396 ret = hwc_prepare_primary(dev, list);
397 break;
398 case HWC_DISPLAY_EXTERNAL:
399 ret = hwc_prepare_external(dev, list);
400 break;
401 case HWC_DISPLAY_VIRTUAL:
402 if(ctx->mHWCVirtual)
403 ret = ctx->mHWCVirtual->prepare(dev, list);
404 break;
405 default:
406 ret = -EINVAL;
407 }
408 }
409
410 ctx->mOverlay->configDone();
411 ctx->mRotMgr->configDone();
412 overlay::Writeback::configDone();
413 // If VD list is deleted, mdp overlay pipe objects and writeback object
414 // are deleted as part of configDone functions.
415 // Proceed with HWCVirtualVDS object deletion.
416 if(ctx->mHWCVirtual)
417 ctx->mHWCVirtual->destroy(ctx, numDisplays, displays);
418
419 return ret;
420 }
421
hwc_eventControl(struct hwc_composer_device_1 * dev,int dpy,int event,int enable)422 static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
423 int event, int enable)
424 {
425 ATRACE_CALL();
426 int ret = 0;
427 hwc_context_t* ctx = (hwc_context_t*)(dev);
428 switch(event) {
429 case HWC_EVENT_VSYNC:
430 if (ctx->vstate.enable == enable)
431 break;
432 ret = hwc_vsync_control(ctx, dpy, enable);
433 if(ret == 0)
434 ctx->vstate.enable = !!enable;
435 ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s",
436 (enable)?"ENABLED":"DISABLED");
437 break;
438 #ifdef QCOM_BSP
439 case HWC_EVENT_ORIENTATION:
440 if(dpy == HWC_DISPLAY_PRIMARY) {
441 Locker::Autolock _l(ctx->mDrawLock);
442 // store the primary display orientation
443 ctx->deviceOrientation = enable;
444 }
445 break;
446 #endif
447 default:
448 ret = -EINVAL;
449 }
450 return ret;
451 }
452
hwc_setPowerMode(struct hwc_composer_device_1 * dev,int dpy,int mode)453 static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
454 int mode)
455 {
456 ATRACE_CALL();
457 hwc_context_t* ctx = (hwc_context_t*)(dev);
458 int ret = 0, value = 0;
459
460 Locker::Autolock _l(ctx->mDrawLock);
461 ALOGD_IF(POWER_MODE_DEBUG, "%s: Setting mode %d on display: %d",
462 __FUNCTION__, mode, dpy);
463
464 switch(mode) {
465 case HWC_POWER_MODE_OFF:
466 // free up all the overlay pipes in use
467 // when we get a blank for either display
468 // makes sure that all pipes are freed
469 ctx->mOverlay->configBegin();
470 ctx->mOverlay->configDone();
471 ctx->mRotMgr->clear();
472 // If VDS is connected, do not clear WB object as it
473 // will end up detaching IOMMU. This is required
474 // to send black frame to WFD sink on power suspend.
475 // Note: With this change, we keep the WriteBack object
476 // alive on power suspend for AD use case.
477 value = FB_BLANK_POWERDOWN;
478 break;
479 case HWC_POWER_MODE_DOZE:
480 case HWC_POWER_MODE_DOZE_SUSPEND:
481 value = FB_BLANK_VSYNC_SUSPEND;
482 break;
483 case HWC_POWER_MODE_NORMAL:
484 value = FB_BLANK_UNBLANK;
485 break;
486 }
487
488 switch(dpy) {
489 case HWC_DISPLAY_PRIMARY:
490 if(ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
491 if(ctx->dpyAttr[dpy].connected) {
492 // When HDMI is connected as primary we clean up resources
493 // and call commit to generate a black frame on the interface.
494 // However, we do not call blank since we need the timing
495 // generator and HDMI core to remain turned on.
496 if((mode == HWC_POWER_MODE_OFF) &&
497 (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd))) {
498 ALOGE("%s: display commit fail for %d", __FUNCTION__, dpy);
499 ret = -1;
500 }
501 }
502 } else {
503 if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) {
504 ALOGE("%s: ioctl FBIOBLANK failed for Primary with error %s"
505 " value %d", __FUNCTION__, strerror(errno), value);
506 return -errno;
507 }
508
509 if(mode == HWC_POWER_MODE_NORMAL && !ctx->mHPDEnabled) {
510 // Enable HPD here, as during bootup POWER_MODE_NORMAL is set
511 // when SF is completely initialized
512 ctx->mHDMIDisplay->setHPD(1);
513 ctx->mHPDEnabled = true;
514 }
515
516 ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
517 }
518 //Deliberate fall through since there is no explicit power mode for
519 //virtual displays.
520 case HWC_DISPLAY_VIRTUAL:
521 if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
522 const int dpy = HWC_DISPLAY_VIRTUAL;
523 if(mode == HWC_POWER_MODE_OFF and
524 (not ctx->dpyAttr[dpy].isPause)) {
525 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
526 ALOGE("%s: displayCommit failed for virtual", __FUNCTION__);
527 ret = -1;
528 }
529 }
530 ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
531 }
532 break;
533 case HWC_DISPLAY_EXTERNAL:
534 if(mode == HWC_POWER_MODE_OFF) {
535 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
536 ALOGE("%s: displayCommit failed for external", __FUNCTION__);
537 ret = -1;
538 }
539 }
540 ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
541 break;
542 default:
543 return -EINVAL;
544 }
545
546 // Configure the color temperature
547 hwc_configure_color_temp(dev);
548
549 ALOGD_IF(POWER_MODE_DEBUG, "%s: Done setting mode %d on display %d",
550 __FUNCTION__, mode, dpy);
551 return ret;
552 }
553
reset_panel(struct hwc_composer_device_1 * dev)554 static void reset_panel(struct hwc_composer_device_1* dev)
555 {
556 int ret = 0;
557 hwc_context_t* ctx = (hwc_context_t*)(dev);
558
559 if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
560 ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__);
561 ctx->mPanelResetStatus = false;
562 return;
563 }
564
565 ALOGD("%s: setting power mode off", __FUNCTION__);
566 ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_OFF);
567 if (ret < 0) {
568 ALOGE("%s: FBIOBLANK failed to BLANK: %s", __FUNCTION__,
569 strerror(errno));
570 }
571
572 ALOGD("%s: setting power mode normal and enabling vsync", __FUNCTION__);
573 ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL);
574 if (ret < 0) {
575 ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
576 strerror(errno));
577 }
578 hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
579
580 ctx->mPanelResetStatus = false;
581 }
582
583
hwc_query(struct hwc_composer_device_1 * dev,int param,int * value)584 static int hwc_query(struct hwc_composer_device_1* dev,
585 int param, int* value)
586 {
587 hwc_context_t* ctx = (hwc_context_t*)(dev);
588 int supported = HWC_DISPLAY_PRIMARY_BIT;
589
590 switch (param) {
591 case HWC_BACKGROUND_LAYER_SUPPORTED:
592 // Not supported for now
593 value[0] = 0;
594 break;
595 case HWC_DISPLAY_TYPES_SUPPORTED:
596 if(ctx->mMDP.hasOverlay) {
597 supported |= HWC_DISPLAY_VIRTUAL_BIT;
598 if(!(qdutils::MDPVersion::getInstance().is8x26() ||
599 qdutils::MDPVersion::getInstance().is8x16() ||
600 qdutils::MDPVersion::getInstance().is8x39()))
601 supported |= HWC_DISPLAY_EXTERNAL_BIT;
602 }
603 value[0] = supported;
604 break;
605 case HWC_FORMAT_RB_SWAP:
606 value[0] = 1;
607 break;
608 case HWC_COLOR_FILL:
609 value[0] = 1;
610 break;
611 default:
612 return -EINVAL;
613 }
614 return 0;
615
616 }
617
618
hwc_set_primary(hwc_context_t * ctx,hwc_display_contents_1_t * list)619 static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
620 ATRACE_CALL();
621 int ret = 0;
622 const int dpy = HWC_DISPLAY_PRIMARY;
623 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive
624 && !ctx->dpyAttr[dpy].isPause) {
625 size_t last = list->numHwLayers - 1;
626 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
627 int fd = -1; //FenceFD from the Copybit(valid in async mode)
628 bool copybitDone = false;
629
630 if (ctx->mCopyBit[dpy]) {
631 if (ctx->mMDP.version < qdutils::MDP_V4_0)
632 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
633 else
634 fd = ctx->mMDPComp[dpy]->drawOverlap(ctx, list);
635 }
636
637 if(list->numHwLayers > 1)
638 hwc_sync(ctx, list, dpy, fd);
639
640 // Dump the layers for primary
641 if(ctx->mHwcDebug[dpy])
642 ctx->mHwcDebug[dpy]->dumpLayers(list);
643
644 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
645 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
646 ret = -1;
647 }
648
649 //TODO We dont check for SKIP flag on this layer because we need PAN
650 //always. Last layer is always FB
651 private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
652 if(copybitDone && ctx->mMDP.version >= qdutils::MDP_V4_0) {
653 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
654 }
655
656 if(isAbcInUse(ctx) == true) {
657 int index = ctx->listStats[dpy].renderBufIndexforABC;
658 hwc_layer_1_t *tempLayer = &list->hwLayers[index];
659 hnd = (private_handle_t *)tempLayer->handle;
660 }
661
662 if(hnd) {
663 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
664 ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
665 ret = -1;
666 }
667 }
668
669 /* When source split is enabled, right ROI will always be NULL since the
670 * ROI for the whole panel generated in a single coordinate system will
671 * be populuated in left ROI. So leave the right ROI untouched */
672 int lSplit = qdutils::MDPVersion::getInstance().isSrcSplit() ? 0 :
673 (isDisplaySplit(ctx, dpy) ? getLeftSplit(ctx, dpy) : 0);
674 qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim(
675 ctx->listStats[dpy].lRoi.left,
676 ctx->listStats[dpy].lRoi.top,
677 ctx->listStats[dpy].lRoi.right - ctx->listStats[dpy].lRoi.left,
678 ctx->listStats[dpy].lRoi.bottom - ctx->listStats[dpy].lRoi.top);
679
680 qhwc::ovutils::Dim rRoi = qhwc::ovutils::Dim(
681 ctx->listStats[dpy].rRoi.left - lSplit,
682 ctx->listStats[dpy].rRoi.top,
683 ctx->listStats[dpy].rRoi.right - ctx->listStats[dpy].rRoi.left,
684 ctx->listStats[dpy].rRoi.bottom - ctx->listStats[dpy].rRoi.top);
685
686 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, lRoi, rRoi)) {
687 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
688 ret = -1;
689 }
690
691 }
692
693 closeAcquireFds(list);
694 return ret;
695 }
696
hwc_set_external(hwc_context_t * ctx,hwc_display_contents_1_t * list)697 static int hwc_set_external(hwc_context_t *ctx,
698 hwc_display_contents_1_t* list)
699 {
700 ATRACE_CALL();
701 int ret = 0;
702
703 const int dpy = HWC_DISPLAY_EXTERNAL;
704
705
706 if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
707 ctx->dpyAttr[dpy].connected &&
708 !ctx->dpyAttr[dpy].isPause) {
709 size_t last = list->numHwLayers - 1;
710 hwc_layer_1_t *fbLayer = &list->hwLayers[last];
711 int fd = -1; //FenceFD from the Copybit(valid in async mode)
712 bool copybitDone = false;
713 if(ctx->mCopyBit[dpy])
714 copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
715
716 if(list->numHwLayers > 1)
717 hwc_sync(ctx, list, dpy, fd);
718
719 // Dump the layers for external
720 if(ctx->mHwcDebug[dpy])
721 ctx->mHwcDebug[dpy]->dumpLayers(list);
722
723 if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
724 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
725 ret = -1;
726 }
727
728 private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
729 if(copybitDone) {
730 hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
731 }
732
733 if(hnd) {
734 if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
735 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
736 ret = -1;
737 }
738 }
739
740 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
741 ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
742 ret = -1;
743 }
744 }
745
746 closeAcquireFds(list);
747 return ret;
748 }
749
hwc_set(hwc_composer_device_1 * dev,size_t numDisplays,hwc_display_contents_1_t ** displays)750 static int hwc_set(hwc_composer_device_1 *dev,
751 size_t numDisplays,
752 hwc_display_contents_1_t** displays)
753 {
754 int ret = 0;
755 hwc_context_t* ctx = (hwc_context_t*)(dev);
756 for (int dpy = 0; dpy < (int)numDisplays; dpy++) {
757 hwc_display_contents_1_t* list = displays[dpy];
758 switch(dpy) {
759 case HWC_DISPLAY_PRIMARY:
760 ret = hwc_set_primary(ctx, list);
761 break;
762 case HWC_DISPLAY_EXTERNAL:
763 ret = hwc_set_external(ctx, list);
764 break;
765 case HWC_DISPLAY_VIRTUAL:
766 if(ctx->mHWCVirtual)
767 ret = ctx->mHWCVirtual->set(ctx, list);
768 break;
769 default:
770 ret = -EINVAL;
771 }
772 }
773 // This is only indicative of how many times SurfaceFlinger posts
774 // frames to the display.
775 CALC_FPS();
776 MDPComp::resetIdleFallBack();
777 ctx->mVideoTransFlag = false;
778 //Was locked at the beginning of prepare
779 ctx->mDrawLock.unlock();
780 return ret;
781 }
782
hwc_getDisplayConfigs(struct hwc_composer_device_1 * dev,int disp,uint32_t * configs,size_t * numConfigs)783 int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
784 uint32_t* configs, size_t* numConfigs) {
785 hwc_context_t* ctx = (hwc_context_t*)(dev);
786
787 Locker::Autolock _l(ctx->mDrawLock);
788 bool hotPluggable = isHotPluggable(ctx, disp);
789 bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
790 // If hotpluggable or virtual displays are inactive return error
791 if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
792 ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
793 return -EINVAL;
794 }
795
796 if (*numConfigs <= 0) {
797 ALOGE("%s Invalid number of configs (%d)", __FUNCTION__, *numConfigs);
798 return -EINVAL;
799 }
800
801 switch(disp) {
802 case HWC_DISPLAY_PRIMARY:
803 if (hotPluggable) {
804 ctx->mHDMIDisplay->getDisplayConfigs(configs, numConfigs);
805 } else {
806 if(ctx->mColorMode->getNumModes() > 0) {
807 *numConfigs = ctx->mColorMode->getNumModes();
808 for (size_t i = 0; i < *numConfigs; i++)
809 configs[i] = (uint32_t) i;
810
811 } else {
812 configs[0] = 0;
813 *numConfigs = 1;
814 }
815 }
816 break;
817 case HWC_DISPLAY_EXTERNAL:
818 ctx->mHDMIDisplay->getDisplayConfigs(configs, numConfigs);
819 break;
820 case HWC_DISPLAY_VIRTUAL:
821 configs[0] = 0;
822 *numConfigs = 1;
823 break;
824 }
825 return 0;
826 }
827
hwc_getDisplayAttributes(struct hwc_composer_device_1 * dev,int disp,uint32_t config,const uint32_t * attributes,int32_t * values)828 int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
829 uint32_t config, const uint32_t* attributes, int32_t* values) {
830
831 hwc_context_t* ctx = (hwc_context_t*)(dev);
832
833 Locker::Autolock _l(ctx->mDrawLock);
834 bool hotPluggable = isHotPluggable(ctx, disp);
835 bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
836 // If hotpluggable or virtual displays are inactive return error
837 if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
838 ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
839 return -EINVAL;
840 }
841
842 uint32_t xres = 0, yres = 0, refresh = 0;
843 int ret = 0;
844 if (hotPluggable) {
845 ret = ctx->mHDMIDisplay->getAttrForConfig(config, xres, yres, refresh);
846 if(ret < 0) {
847 ALOGE("%s Error getting attributes for config %d",
848 __FUNCTION__, config);
849 return ret;
850 }
851 }
852
853 for (size_t i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
854 switch (attributes[i]) {
855 case HWC_DISPLAY_VSYNC_PERIOD:
856 values[i] =
857 hotPluggable ? refresh : ctx->dpyAttr[disp].vsync_period;
858 break;
859 case HWC_DISPLAY_WIDTH:
860 if (ctx->dpyAttr[disp].customFBSize)
861 values[i] = ctx->dpyAttr[disp].xres_new;
862 else
863 values[i] = hotPluggable ? xres : ctx->dpyAttr[disp].xres;
864
865 ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
866 values[i]);
867 break;
868 case HWC_DISPLAY_HEIGHT:
869 if (ctx->dpyAttr[disp].customFBSize)
870 values[i] = ctx->dpyAttr[disp].yres_new;
871 else
872 values[i] = hotPluggable ? yres : ctx->dpyAttr[disp].yres;
873 ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
874 values[i]);
875 break;
876 case HWC_DISPLAY_DPI_X:
877 values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
878 break;
879 case HWC_DISPLAY_DPI_Y:
880 values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
881 break;
882 case HWC_DISPLAY_COLOR_TRANSFORM:
883 values[i] = ctx->mColorMode->getModeForIndex(config);
884 break;
885 default:
886 ALOGE("Unknown display attribute %d",
887 attributes[i]);
888 return -EINVAL;
889 }
890 }
891 return 0;
892 }
893
hwc_dump(struct hwc_composer_device_1 * dev,char * buff,int buff_len)894 void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
895 {
896 hwc_context_t* ctx = (hwc_context_t*)(dev);
897 Locker::Autolock _l(ctx->mDrawLock);
898 android::String8 aBuf("");
899 dumpsys_log(aBuf, "Qualcomm HWC state:\n");
900 dumpsys_log(aBuf, " MDPVersion=%d\n", ctx->mMDP.version);
901 dumpsys_log(aBuf, " DisplayPanel=%c\n", ctx->mMDP.panel);
902 dumpsys_log(aBuf, " DynRefreshRate=%d\n",
903 ctx->dpyAttr[HWC_DISPLAY_PRIMARY].dynRefreshRate);
904 for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
905 if(ctx->mMDPComp[dpy])
906 ctx->mMDPComp[dpy]->dump(aBuf, ctx);
907 }
908 char ovDump[2048] = {'\0'};
909 ctx->mOverlay->getDump(ovDump, 2048);
910 dumpsys_log(aBuf, ovDump);
911 ovDump[0] = '\0';
912 ctx->mRotMgr->getDump(ovDump, 1024);
913 dumpsys_log(aBuf, ovDump);
914 ovDump[0] = '\0';
915 if(Writeback::getDump(ovDump, 1024)) {
916 dumpsys_log(aBuf, ovDump);
917 ovDump[0] = '\0';
918 }
919 strlcpy(buff, aBuf.string(), buff_len);
920 }
921
hwc_getActiveConfig(struct hwc_composer_device_1 * dev,int disp)922 int hwc_getActiveConfig(struct hwc_composer_device_1* dev, int disp)
923 {
924 hwc_context_t* ctx = (hwc_context_t*)(dev);
925
926 Locker::Autolock _l(ctx->mDrawLock);
927 bool hotPluggable = isHotPluggable(ctx, disp);
928 bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
929 // If hotpluggable or virtual displays are inactive return error
930 if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
931 ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
932 return -EINVAL;
933 }
934
935 // For use cases when primary panel is the default interface we only have
936 // the default config (0th index)
937 if (!hotPluggable && disp == HWC_DISPLAY_PRIMARY) {
938 return ctx->mColorMode->getActiveModeIndex();
939 } else if (isVirtualDisplay) {
940 return 0;
941 }
942
943 return ctx->mHDMIDisplay->getActiveConfig();
944 }
945
hwc_setActiveConfig(struct hwc_composer_device_1 * dev,int disp,int index)946 int hwc_setActiveConfig(struct hwc_composer_device_1* dev, int disp, int index)
947 {
948 hwc_context_t* ctx = (hwc_context_t*)(dev);
949
950 Locker::Autolock _l(ctx->mDrawLock);
951 bool hotPluggable = isHotPluggable(ctx, disp);
952 bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
953 // If hotpluggable or virtual displays are inactive return error
954 if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
955 ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
956 return -EINVAL;
957 }
958
959 // For use cases when primary panel is the default interface we only switch
960 // color modes
961 if(!hotPluggable && disp == HWC_DISPLAY_PRIMARY) {
962 return ctx->mColorMode->applyModeByIndex(index);
963 } else if (isVirtualDisplay) {
964 // virtual supports only the default config (0th index)
965 return (index == 0) ? index : -EINVAL;
966 }
967
968 return ctx->mHDMIDisplay->setActiveConfig(index);
969 }
970
hwc_device_close(struct hw_device_t * dev)971 static int hwc_device_close(struct hw_device_t *dev)
972 {
973 if(!dev) {
974 ALOGE("%s: NULL device pointer", __FUNCTION__);
975 return -1;
976 }
977 closeContext((hwc_context_t*)dev);
978 free(dev);
979
980 return 0;
981 }
982
hwc_device_open(const struct hw_module_t * module,const char * name,struct hw_device_t ** device)983 static int hwc_device_open(const struct hw_module_t* module, const char* name,
984 struct hw_device_t** device)
985 {
986 int status = -EINVAL;
987
988 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
989 struct hwc_context_t *dev;
990 dev = (hwc_context_t*)malloc(sizeof(*dev));
991 if(dev == NULL)
992 return status;
993 memset(dev, 0, sizeof(*dev));
994
995 //Initialize hwc context
996 initContext(dev);
997
998 //Setup HWC methods
999 dev->device.common.tag = HARDWARE_DEVICE_TAG;
1000 dev->device.common.version = HWC_DEVICE_API_VERSION_1_5;
1001 dev->device.common.module = const_cast<hw_module_t*>(module);
1002 dev->device.common.close = hwc_device_close;
1003 dev->device.prepare = hwc_prepare;
1004 dev->device.set = hwc_set;
1005 dev->device.eventControl = hwc_eventControl;
1006 dev->device.setPowerMode = hwc_setPowerMode;
1007 dev->device.query = hwc_query;
1008 dev->device.registerProcs = hwc_registerProcs;
1009 dev->device.dump = hwc_dump;
1010 dev->device.getDisplayConfigs = hwc_getDisplayConfigs;
1011 dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
1012 dev->device.getActiveConfig = hwc_getActiveConfig;
1013 dev->device.setActiveConfig = hwc_setActiveConfig;
1014 *device = &dev->device.common;
1015 status = 0;
1016 }
1017 return status;
1018 }
1019