blob: dcc73ac1da654e5f8c3d6b7b40985bf4c0c77663
1 | /* |
2 | * Copyright (c) 2017 Amlogic, Inc. All rights reserved. |
3 | * |
4 | * This source code is subject to the terms and conditions defined in the |
5 | * file 'LICENSE' which is part of this source code package. |
6 | * |
7 | * Description: |
8 | */ |
9 | |
10 | #include <unistd.h> |
11 | #include <thread> |
12 | #include <mutex> |
13 | #include <condition_variable> |
14 | |
15 | #include <BasicTypes.h> |
16 | #include <MesonLog.h> |
17 | #include <DebugHelper.h> |
18 | #include <HwcConfig.h> |
19 | #include <HwcVsync.h> |
20 | #include <HwcDisplayPipe.h> |
21 | #include <misc.h> |
22 | #include <systemcontrol.h> |
23 | |
24 | #include "MesonHwc2Defs.h" |
25 | #include "MesonHwc2.h" |
26 | #include "VirtualDisplay.h" |
27 | |
28 | #define GET_REQUEST_FROM_PROP 1 |
29 | |
30 | #define CHECK_DISPLAY_VALID(display) \ |
31 | if (isDisplayValid(display) == false) { \ |
32 | MESON_LOGE("(%s) met invalid display id (%d)", \ |
33 | __func__, (int)display); \ |
34 | return HWC2_ERROR_BAD_DISPLAY; \ |
35 | } |
36 | |
37 | #define GET_HWC_DISPLAY(display) \ |
38 | std::shared_ptr<Hwc2Display> hwcDisplay; \ |
39 | std::map<hwc2_display_t, std::shared_ptr<Hwc2Display>>::iterator it = \ |
40 | mDisplays.find(display); \ |
41 | if (it != mDisplays.end()) { \ |
42 | hwcDisplay = it->second; \ |
43 | } else {\ |
44 | MESON_LOGE("(%s) met invalid display id (%d)",\ |
45 | __func__, (int)display); \ |
46 | return HWC2_ERROR_BAD_DISPLAY; \ |
47 | } |
48 | |
49 | #define GET_HWC_LAYER(display, id) \ |
50 | std::shared_ptr<Hwc2Layer> hwcLayer = display->getLayerById(id); \ |
51 | if (hwcLayer.get() == NULL) { \ |
52 | MESON_LOGE("(%s) met invalid layer id (%d) in display (%p)",\ |
53 | __func__, (int)id, display.get()); \ |
54 | return HWC2_ERROR_BAD_LAYER; \ |
55 | } |
56 | |
57 | |
58 | #ifdef GET_REQUEST_FROM_PROP |
59 | static bool m3DMode = false; |
60 | static bool mKeyStoneMode = false; |
61 | #endif |
62 | |
63 | ANDROID_SINGLETON_STATIC_INSTANCE(MesonHwc2) |
64 | |
65 | /************************************************************ |
66 | * Hal Interface |
67 | ************************************************************/ |
68 | void MesonHwc2::dump(uint32_t* outSize, char* outBuffer) { |
69 | if (outBuffer == NULL) { |
70 | *outSize = 8192; |
71 | return ; |
72 | } |
73 | |
74 | String8 dumpstr; |
75 | DebugHelper::getInstance().resolveCmd(); |
76 | |
77 | #ifdef HWC_RELEASE |
78 | dumpstr.append("\nMesonHwc2 state(RELEASE):\n"); |
79 | #else |
80 | dumpstr.append("\nMesonHwc2 state(DEBUG):\n"); |
81 | #endif |
82 | |
83 | if (DebugHelper::getInstance().dumpDetailInfo()) { |
84 | HwcConfig::dump(dumpstr); |
85 | } |
86 | |
87 | // dump composer status |
88 | std::map<hwc2_display_t, std::shared_ptr<Hwc2Display>>::iterator it; |
89 | for (it = mDisplays.begin(); it != mDisplays.end(); it++) { |
90 | it->second->dump(dumpstr); |
91 | } |
92 | |
93 | DebugHelper::getInstance().dump(dumpstr); |
94 | dumpstr.append("\n"); |
95 | |
96 | strncpy(outBuffer, dumpstr.string(), dumpstr.size() > 8192 ? 8191 : dumpstr.size()); |
97 | } |
98 | |
99 | void MesonHwc2::getCapabilities(uint32_t* outCount, |
100 | int32_t* outCapabilities) { |
101 | *outCount = 1; |
102 | if (outCapabilities) { |
103 | *outCount = 1; |
104 | outCapabilities[0] = HWC2_CAPABILITY_SIDEBAND_STREAM; |
105 | } |
106 | } |
107 | |
108 | int32_t MesonHwc2::getClientTargetSupport(hwc2_display_t display, |
109 | uint32_t width __unused, uint32_t height __unused, int32_t format, int32_t dataspace) { |
110 | GET_HWC_DISPLAY(display); |
111 | if (format == HAL_PIXEL_FORMAT_RGBA_8888 && |
112 | dataspace == HAL_DATASPACE_UNKNOWN) { |
113 | return HWC2_ERROR_NONE; |
114 | } |
115 | |
116 | MESON_LOGE("getClientTargetSupport failed: format (%d), dataspace (%d)", |
117 | format, dataspace); |
118 | return HWC2_ERROR_UNSUPPORTED; |
119 | } |
120 | |
121 | int32_t MesonHwc2::registerCallback(int32_t descriptor, |
122 | hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) { |
123 | hwc2_error_t ret = HWC2_ERROR_NONE; |
124 | |
125 | switch (descriptor) { |
126 | case HWC2_CALLBACK_HOTPLUG: |
127 | /* For android: |
128 | When primary display is hdmi, we should always return connected event |
129 | to surfaceflinger, or surfaceflinger will not boot and wait |
130 | connected event. |
131 | */ |
132 | mHotplugFn = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer); |
133 | mHotplugData = callbackData; |
134 | |
135 | /*always to call hotplug for primary display, |
136 | * for android always think primary is always connected. |
137 | */ |
138 | if (mHotplugFn) { |
139 | mHotplugFn(mHotplugData, HWC_DISPLAY_PRIMARY, true); |
140 | if (HwcConfig::getDisplayNum() > 1) { |
141 | mHotplugFn(mHotplugData, HWC_DISPLAY_EXTERNAL, true); |
142 | } |
143 | } |
144 | break; |
145 | case HWC2_CALLBACK_REFRESH: |
146 | mRefreshFn = reinterpret_cast<HWC2_PFN_REFRESH>(pointer); |
147 | mRefreshData = callbackData; |
148 | break; |
149 | case HWC2_CALLBACK_VSYNC: |
150 | mVsyncFn = reinterpret_cast<HWC2_PFN_VSYNC>(pointer); |
151 | mVsyncData = callbackData; |
152 | break; |
153 | |
154 | default: |
155 | MESON_LOGE("register unknown callback (%d)", descriptor); |
156 | ret = HWC2_ERROR_UNSUPPORTED; |
157 | break; |
158 | } |
159 | |
160 | return ret; |
161 | } |
162 | |
163 | int32_t MesonHwc2::getDisplayName(hwc2_display_t display, |
164 | uint32_t* outSize, char* outName) { |
165 | GET_HWC_DISPLAY(display); |
166 | const char * name = hwcDisplay->getName(); |
167 | if (name == NULL) { |
168 | MESON_LOGE("getDisplayName (%d) failed", (int)display); |
169 | } else { |
170 | *outSize = strlen(name) + 1; |
171 | if (outName) { |
172 | strcpy(outName, name); |
173 | } |
174 | } |
175 | return HWC2_ERROR_NONE; |
176 | } |
177 | |
178 | int32_t MesonHwc2::getDisplayType(hwc2_display_t display, |
179 | int32_t* outType) { |
180 | GET_HWC_DISPLAY(display); |
181 | |
182 | if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES) { |
183 | *outType = HWC2_DISPLAY_TYPE_PHYSICAL; |
184 | } else { |
185 | *outType = HWC2_DISPLAY_TYPE_VIRTUAL; |
186 | } |
187 | |
188 | return HWC2_ERROR_NONE; |
189 | } |
190 | |
191 | int32_t MesonHwc2::getDozeSupport(hwc2_display_t display, |
192 | int32_t* outSupport) { |
193 | /*No doze support now.*/ |
194 | CHECK_DISPLAY_VALID(display); |
195 | *outSupport = 0; |
196 | return HWC2_ERROR_NONE; |
197 | } |
198 | |
199 | int32_t MesonHwc2::getColorModes(hwc2_display_t display, |
200 | uint32_t* outNumModes, int32_t* outModes) { |
201 | CHECK_DISPLAY_VALID(display); |
202 | /*Only support native color mode.*/ |
203 | *outNumModes = 1; |
204 | if (outModes) { |
205 | outModes[0] = HAL_COLOR_MODE_NATIVE; |
206 | } |
207 | return HWC2_ERROR_NONE; |
208 | } |
209 | |
210 | int32_t MesonHwc2::setColorMode(hwc2_display_t display, int32_t mode __unused) { |
211 | CHECK_DISPLAY_VALID(display); |
212 | if (mode < HAL_COLOR_MODE_NATIVE) |
213 | return HWC2_ERROR_BAD_PARAMETER; |
214 | |
215 | if (mode == HAL_COLOR_MODE_NATIVE) |
216 | return HWC2_ERROR_NONE; |
217 | else |
218 | return HWC2_ERROR_UNSUPPORTED; |
219 | } |
220 | |
221 | int32_t MesonHwc2::setColorTransform(hwc2_display_t display, |
222 | const float* matrix, int32_t hint) { |
223 | GET_HWC_DISPLAY(display); |
224 | return hwcDisplay->setColorTransform(matrix, (android_color_transform_t)hint); |
225 | } |
226 | |
227 | int32_t MesonHwc2::getHdrCapabilities(hwc2_display_t display, |
228 | uint32_t* outNumTypes, int32_t* outTypes, float* outMaxLuminance, |
229 | float* outMaxAverageLuminance, float* outMinLuminance) { |
230 | GET_HWC_DISPLAY(display); |
231 | const drm_hdr_capabilities_t * caps = hwcDisplay->getHdrCapabilities(); |
232 | if (caps) { |
233 | bool getInfo = false; |
234 | if (outTypes) |
235 | getInfo = true; |
236 | |
237 | if (caps->DolbyVisionSupported) { |
238 | *outNumTypes = *outNumTypes + 1; |
239 | if (getInfo) { |
240 | *outTypes++ = HAL_HDR_DOLBY_VISION; |
241 | } |
242 | } |
243 | if (caps->HLGSupported) { |
244 | *outNumTypes = *outNumTypes + 1; |
245 | if (getInfo) { |
246 | *outTypes++ = HAL_HDR_HLG; |
247 | } |
248 | } |
249 | if (caps->HDR10Supported) { |
250 | *outNumTypes = *outNumTypes + 1; |
251 | if (getInfo) { |
252 | *outTypes++ = HAL_HDR_HDR10; |
253 | } |
254 | } |
255 | |
256 | if (caps->HDR10PlusSupported) { |
257 | *outNumTypes = *outNumTypes + 1; |
258 | if (getInfo) { |
259 | *outTypes++ = HAL_HDR_HDR10_PLUS; |
260 | } |
261 | } |
262 | |
263 | if (getInfo) { |
264 | *outMaxLuminance = caps->maxLuminance; |
265 | *outMaxAverageLuminance = caps->avgLuminance; |
266 | *outMinLuminance = caps->minLuminance; |
267 | } |
268 | } else { |
269 | *outNumTypes = 0; |
270 | } |
271 | |
272 | return HWC2_ERROR_NONE; |
273 | } |
274 | |
275 | int32_t MesonHwc2::setPowerMode(hwc2_display_t display, |
276 | int32_t mode) { |
277 | GET_HWC_DISPLAY(display); |
278 | return hwcDisplay->setPowerMode((hwc2_power_mode_t)mode); |
279 | } |
280 | |
281 | int32_t MesonHwc2::setVsyncEnable(hwc2_display_t display, |
282 | int32_t enabled) { |
283 | GET_HWC_DISPLAY(display); |
284 | return hwcDisplay->setVsyncEnable((hwc2_vsync_t)enabled); |
285 | } |
286 | |
287 | int32_t MesonHwc2::getActiveConfig(hwc2_display_t display, |
288 | hwc2_config_t* outConfig) { |
289 | GET_HWC_DISPLAY(display); |
290 | return hwcDisplay->getActiveConfig(outConfig); |
291 | } |
292 | |
293 | int32_t MesonHwc2::getDisplayConfigs(hwc2_display_t display, |
294 | uint32_t* outNumConfigs, hwc2_config_t* outConfigs) { |
295 | GET_HWC_DISPLAY(display); |
296 | return hwcDisplay->getDisplayConfigs(outNumConfigs, outConfigs); |
297 | } |
298 | |
299 | int32_t MesonHwc2::setActiveConfig(hwc2_display_t display, |
300 | hwc2_config_t config) { |
301 | GET_HWC_DISPLAY(display); |
302 | return hwcDisplay->setActiveConfig(config); |
303 | } |
304 | |
305 | int32_t MesonHwc2::getDisplayAttribute(hwc2_display_t display, |
306 | hwc2_config_t config, int32_t attribute, int32_t* outValue) { |
307 | GET_HWC_DISPLAY(display); |
308 | return hwcDisplay->getDisplayAttribute(config, attribute, outValue); |
309 | } |
310 | |
311 | /*************Virtual display api below*************/ |
312 | int32_t MesonHwc2::createVirtualDisplay(uint32_t width, uint32_t height, |
313 | int32_t* format, hwc2_display_t* outDisplay) { |
314 | MESON_LOG_EMPTY_FUN(); |
315 | UNUSED(width); |
316 | UNUSED(height); |
317 | UNUSED(format); |
318 | UNUSED(outDisplay); |
319 | return HWC2_ERROR_NONE; |
320 | } |
321 | |
322 | int32_t MesonHwc2::destroyVirtualDisplay(hwc2_display_t display) { |
323 | MESON_LOG_EMPTY_FUN(); |
324 | UNUSED(display); |
325 | return HWC2_ERROR_NONE; |
326 | } |
327 | |
328 | int32_t MesonHwc2::setOutputBuffer(hwc2_display_t display, |
329 | buffer_handle_t buffer, int32_t releaseFence) { |
330 | MESON_LOG_EMPTY_FUN(); |
331 | UNUSED(display); |
332 | UNUSED(buffer); |
333 | UNUSED(releaseFence); |
334 | return HWC2_ERROR_NONE; |
335 | } |
336 | |
337 | uint32_t MesonHwc2::getMaxVirtualDisplayCount() { |
338 | return MESON_VIRTUAL_DISPLAY_MAX_COUNT; |
339 | } |
340 | |
341 | /*************Compose api below*************/ |
342 | int32_t MesonHwc2::acceptDisplayChanges(hwc2_display_t display) { |
343 | GET_HWC_DISPLAY(display); |
344 | return hwcDisplay->acceptDisplayChanges(); |
345 | } |
346 | |
347 | int32_t MesonHwc2::getChangedCompositionTypes( hwc2_display_t display, |
348 | uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) { |
349 | GET_HWC_DISPLAY(display); |
350 | return hwcDisplay->getChangedCompositionTypes(outNumElements, |
351 | outLayers, outTypes); |
352 | } |
353 | |
354 | int32_t MesonHwc2::getDisplayRequests(hwc2_display_t display, |
355 | int32_t* outDisplayRequests, uint32_t* outNumElements, |
356 | hwc2_layer_t* outLayers, int32_t* outLayerRequests) { |
357 | GET_HWC_DISPLAY(display); |
358 | return hwcDisplay->getDisplayRequests(outDisplayRequests, outNumElements, |
359 | outLayers, outLayerRequests); |
360 | } |
361 | |
362 | int32_t MesonHwc2::setClientTarget(hwc2_display_t display, |
363 | buffer_handle_t target, int32_t acquireFence, |
364 | int32_t dataspace, hwc_region_t damage) { |
365 | GET_HWC_DISPLAY(display); |
366 | return hwcDisplay->setClientTarget(target, acquireFence, |
367 | dataspace, damage); |
368 | } |
369 | |
370 | int32_t MesonHwc2::getReleaseFences(hwc2_display_t display, |
371 | uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outFences) { |
372 | GET_HWC_DISPLAY(display); |
373 | return hwcDisplay->getReleaseFences(outNumElements, |
374 | outLayers, outFences); |
375 | } |
376 | |
377 | int32_t MesonHwc2::validateDisplay(hwc2_display_t display, |
378 | uint32_t* outNumTypes, uint32_t* outNumRequests) { |
379 | GET_HWC_DISPLAY(display); |
380 | /*handle display request*/ |
381 | uint32_t request = getDisplayRequest(); |
382 | setCalibrateInfo(display); |
383 | if (request != 0) { |
384 | handleDisplayRequest(request); |
385 | } |
386 | |
387 | return hwcDisplay->validateDisplay(outNumTypes, |
388 | outNumRequests); |
389 | } |
390 | |
391 | int32_t MesonHwc2::presentDisplay(hwc2_display_t display, |
392 | int32_t* outPresentFence) { |
393 | GET_HWC_DISPLAY(display); |
394 | return hwcDisplay->presentDisplay(outPresentFence); |
395 | } |
396 | |
397 | /*************Layer api below*************/ |
398 | int32_t MesonHwc2::createLayer(hwc2_display_t display, hwc2_layer_t* outLayer) { |
399 | GET_HWC_DISPLAY(display); |
400 | return hwcDisplay->createLayer(outLayer); |
401 | } |
402 | |
403 | int32_t MesonHwc2::destroyLayer(hwc2_display_t display, hwc2_layer_t layer) { |
404 | GET_HWC_DISPLAY(display); |
405 | return hwcDisplay->destroyLayer(layer); |
406 | } |
407 | |
408 | int32_t MesonHwc2::setCursorPosition(hwc2_display_t display, |
409 | hwc2_layer_t layer, int32_t x, int32_t y) { |
410 | GET_HWC_DISPLAY(display); |
411 | return hwcDisplay->setCursorPosition(layer, x, y); |
412 | } |
413 | |
414 | int32_t MesonHwc2::setLayerBuffer(hwc2_display_t display, hwc2_layer_t layer, |
415 | buffer_handle_t buffer, int32_t acquireFence) { |
416 | GET_HWC_DISPLAY(display); |
417 | GET_HWC_LAYER(hwcDisplay, layer); |
418 | return hwcLayer->setBuffer(buffer, acquireFence); |
419 | } |
420 | |
421 | int32_t MesonHwc2::setLayerSurfaceDamage(hwc2_display_t display, |
422 | hwc2_layer_t layer, hwc_region_t damage) { |
423 | GET_HWC_DISPLAY(display); |
424 | GET_HWC_LAYER(hwcDisplay, layer); |
425 | return hwcLayer->setSurfaceDamage(damage); |
426 | } |
427 | |
428 | int32_t MesonHwc2::setLayerBlendMode(hwc2_display_t display, |
429 | hwc2_layer_t layer, int32_t mode) { |
430 | GET_HWC_DISPLAY(display); |
431 | GET_HWC_LAYER(hwcDisplay, layer); |
432 | return hwcLayer->setBlendMode((hwc2_blend_mode_t)mode); |
433 | } |
434 | |
435 | int32_t MesonHwc2::setLayerColor(hwc2_display_t display, |
436 | hwc2_layer_t layer, hwc_color_t color) { |
437 | GET_HWC_DISPLAY(display); |
438 | GET_HWC_LAYER(hwcDisplay, layer); |
439 | return hwcLayer->setColor(color); |
440 | } |
441 | |
442 | int32_t MesonHwc2::setLayerCompositionType(hwc2_display_t display, |
443 | hwc2_layer_t layer, int32_t type) { |
444 | GET_HWC_DISPLAY(display); |
445 | GET_HWC_LAYER(hwcDisplay, layer); |
446 | return hwcLayer->setCompositionType((hwc2_composition_t)type); |
447 | } |
448 | |
449 | int32_t MesonHwc2::setLayerDataspace(hwc2_display_t display, |
450 | hwc2_layer_t layer, int32_t dataspace) { |
451 | GET_HWC_DISPLAY(display); |
452 | GET_HWC_LAYER(hwcDisplay, layer); |
453 | return hwcLayer->setDataspace((android_dataspace_t)dataspace); |
454 | } |
455 | |
456 | int32_t MesonHwc2::setLayerDisplayFrame(hwc2_display_t display, |
457 | hwc2_layer_t layer, hwc_rect_t frame) { |
458 | GET_HWC_DISPLAY(display); |
459 | GET_HWC_LAYER(hwcDisplay, layer); |
460 | return hwcLayer->setDisplayFrame(frame); |
461 | } |
462 | |
463 | int32_t MesonHwc2::setLayerPlaneAlpha(hwc2_display_t display, |
464 | hwc2_layer_t layer, float alpha) { |
465 | GET_HWC_DISPLAY(display); |
466 | GET_HWC_LAYER(hwcDisplay, layer); |
467 | return hwcLayer->setPlaneAlpha(alpha); |
468 | } |
469 | |
470 | int32_t MesonHwc2::setLayerSidebandStream(hwc2_display_t display, |
471 | hwc2_layer_t layer, const native_handle_t* stream) { |
472 | GET_HWC_DISPLAY(display); |
473 | GET_HWC_LAYER(hwcDisplay, layer); |
474 | return hwcLayer->setSidebandStream(stream); |
475 | } |
476 | |
477 | int32_t MesonHwc2::setLayerSourceCrop(hwc2_display_t display, |
478 | hwc2_layer_t layer, hwc_frect_t crop) { |
479 | GET_HWC_DISPLAY(display); |
480 | GET_HWC_LAYER(hwcDisplay, layer); |
481 | return hwcLayer->setSourceCrop(crop); |
482 | } |
483 | |
484 | int32_t MesonHwc2::setLayerTransform(hwc2_display_t display, |
485 | hwc2_layer_t layer, int32_t transform) { |
486 | GET_HWC_DISPLAY(display); |
487 | GET_HWC_LAYER(hwcDisplay, layer); |
488 | return hwcLayer->setTransform((hwc_transform_t)transform); |
489 | } |
490 | |
491 | int32_t MesonHwc2::setLayerVisibleRegion(hwc2_display_t display, |
492 | hwc2_layer_t layer, hwc_region_t visible) { |
493 | GET_HWC_DISPLAY(display); |
494 | GET_HWC_LAYER(hwcDisplay, layer); |
495 | return hwcLayer->setVisibleRegion(visible); |
496 | } |
497 | |
498 | int32_t MesonHwc2::setLayerZorder(hwc2_display_t display, |
499 | hwc2_layer_t layer, uint32_t z) { |
500 | GET_HWC_DISPLAY(display); |
501 | GET_HWC_LAYER(hwcDisplay, layer); |
502 | return hwcLayer->setZorder(z); |
503 | } |
504 | |
505 | int32_t MesonHwc2::getRenderIntents(hwc2_display_t display, |
506 | int32_t mode, uint32_t* outNumIntents, int32_t* outIntents) { |
507 | GET_HWC_DISPLAY(display); |
508 | |
509 | if (mode < HAL_COLOR_MODE_NATIVE) |
510 | return HWC2_ERROR_BAD_PARAMETER; |
511 | if (mode != HAL_COLOR_MODE_NATIVE) |
512 | return HWC2_ERROR_UNSUPPORTED; |
513 | |
514 | *outNumIntents = 1; |
515 | if (outIntents) { |
516 | *outIntents = HAL_RENDER_INTENT_COLORIMETRIC; |
517 | } |
518 | |
519 | return HWC2_ERROR_NONE; |
520 | } |
521 | |
522 | int32_t MesonHwc2::setColorModeWithRenderIntent( |
523 | hwc2_display_t display, int32_t mode, int32_t intent) { |
524 | GET_HWC_DISPLAY(display); |
525 | |
526 | if (mode < HAL_COLOR_MODE_NATIVE || |
527 | intent < HAL_RENDER_INTENT_COLORIMETRIC) |
528 | return HWC2_ERROR_BAD_PARAMETER; |
529 | if (mode != HAL_COLOR_MODE_NATIVE || |
530 | intent != HAL_RENDER_INTENT_COLORIMETRIC) |
531 | return HWC2_ERROR_UNSUPPORTED; |
532 | |
533 | return HWC2_ERROR_NONE; |
534 | } |
535 | |
536 | #ifdef HWC_HDR_METADATA_SUPPORT |
537 | int32_t MesonHwc2::setLayerPerFrameMetadata( |
538 | hwc2_display_t display, hwc2_layer_t layer, |
539 | uint32_t numElements, const int32_t* /*hw2_per_frame_metadata_key_t*/ keys, |
540 | const float* metadata) { |
541 | GET_HWC_DISPLAY(display); |
542 | GET_HWC_LAYER(hwcDisplay, layer); |
543 | return hwcLayer->setPerFrameMetadata(numElements, keys, metadata); |
544 | } |
545 | |
546 | int32_t MesonHwc2::getPerFrameMetadataKeys( |
547 | hwc2_display_t display, |
548 | uint32_t* outNumKeys, |
549 | int32_t* /*hwc2_per_frame_metadata_key_t*/ outKeys) { |
550 | GET_HWC_DISPLAY(display); |
551 | return hwcDisplay->getFrameMetadataKeys(outNumKeys, outKeys); |
552 | } |
553 | #endif |
554 | |
555 | int32_t MesonHwc2::getDisplayIdentificationData(hwc2_display_t display, uint8_t* outPort, |
556 | uint32_t* outDataSize, uint8_t* outData) { |
557 | std::vector<uint8_t> edid; |
558 | uint32_t port; |
559 | GET_HWC_DISPLAY(display); |
560 | if (0 != hwcDisplay->getDisplayIdentificationData(port, edid)) { |
561 | return HWC2_ERROR_UNSUPPORTED; |
562 | } |
563 | if (outData == nullptr) { |
564 | *outDataSize = edid.size(); |
565 | } else { |
566 | if (*outDataSize != edid.size()) { |
567 | return HWC2_ERROR_BAD_PARAMETER; |
568 | } |
569 | memcpy(outData, edid.data(), sizeof(uint8_t) * edid.size()); |
570 | } |
571 | *outPort = (uint8_t)port; |
572 | return HWC2_ERROR_NONE; |
573 | } |
574 | |
575 | int32_t MesonHwc2::getDisplayCapabilities(hwc2_display_t display, uint32_t* outNumCapabilities, uint32_t* outCapabilities) { |
576 | GET_HWC_DISPLAY(display); |
577 | return hwcDisplay->getDisplayCapabilities(outNumCapabilities, outCapabilities); |
578 | } |
579 | |
580 | int32_t MesonHwc2::getDisplayBrightnessSupport(hwc2_display_t display, bool* outSupport) { |
581 | GET_HWC_DISPLAY(display); |
582 | *outSupport = false; |
583 | return HWC2_ERROR_NONE; |
584 | } |
585 | |
586 | int32_t MesonHwc2::setDisplayBrightness(hwc2_display_t display, float brightness) { |
587 | GET_HWC_DISPLAY(display); |
588 | (void) brightness; |
589 | return HWC2_ERROR_UNSUPPORTED; |
590 | } |
591 | |
592 | /**********************Amlogic ext display interface*******************/ |
593 | int32_t MesonHwc2::setPostProcessor(bool bEnable) { |
594 | mDisplayRequests |= bEnable ? rPostProcessorStart : rPostProcessorStop; |
595 | return 0; |
596 | } |
597 | |
598 | int32_t MesonHwc2::setCalibrateInfo(hwc2_display_t display){ |
599 | GET_HWC_DISPLAY(display); |
600 | int32_t caliX,caliY,caliW,caliH; |
601 | static int cali[4]; |
602 | drm_mode_info_t mDispMode; |
603 | hwcDisplay->getDispMode(mDispMode); |
604 | |
605 | if (HwcConfig::getPipeline() == HWC_PIPE_LOOPBACK) { |
606 | caliX = caliY = 0; |
607 | caliW = mDispMode.pixelW; |
608 | caliH = mDispMode.pixelH; |
609 | #ifdef GET_REQUEST_FROM_PROP |
610 | if (mKeyStoneMode) { |
611 | caliX = 1; |
612 | caliY = 1; |
613 | caliW = mDispMode.pixelW - 2; |
614 | caliH = mDispMode.pixelH - 2; |
615 | } |
616 | #endif |
617 | } else { |
618 | /*default info*/ |
619 | caliX = 0; |
620 | caliY = 0; |
621 | caliW = mDispMode.pixelW; |
622 | caliH = mDispMode.pixelH; |
623 | if (!HwcConfig::preDisplayCalibrateEnabled()) { |
624 | /*get post calibrate info.*/ |
625 | /*for interlaced, we do thing, osd driver will take care of it.*/ |
626 | int calibrateCoordinates[4]; |
627 | std::string dispModeStr(mDispMode.name); |
628 | if (0 == sc_get_osd_position(dispModeStr, calibrateCoordinates)) { |
629 | memcpy(cali, calibrateCoordinates, sizeof(int) * 4); |
630 | } else { |
631 | MESON_LOGD("(%s): sc_get_osd_position failed, use backup coordinates.", __func__); |
632 | } |
633 | caliX = cali[0]; |
634 | caliY = cali[1]; |
635 | caliW = cali[2]; |
636 | caliH = cali[3]; |
637 | } |
638 | } |
639 | return hwcDisplay->setCalibrateInfo(caliX,caliY,caliW,caliH); |
640 | } |
641 | |
642 | uint32_t MesonHwc2::getDisplayRequest() { |
643 | /*read extend prop to update display request.*/ |
644 | #ifdef GET_REQUEST_FROM_PROP |
645 | if (HwcConfig::getPipeline() == HWC_PIPE_LOOPBACK) { |
646 | char val[PROP_VALUE_LEN_MAX]; |
647 | bool bVal = false; |
648 | |
649 | if (HwcConfig::alwaysVdinLoopback()) { |
650 | /*get 3dmode status*/ |
651 | bVal = !sys_get_bool_prop("vendor.hwc.postprocessor", true); |
652 | if (m3DMode != bVal) { |
653 | mDisplayRequests |= bVal ? rPostProcessorStop : rPostProcessorStart; |
654 | m3DMode = bVal; |
655 | if (m3DMode) |
656 | mKeyStoneMode = false; |
657 | } |
658 | |
659 | if (!m3DMode) { |
660 | /*get keystone status*/ |
661 | bVal = false; |
662 | if (sys_get_string_prop("persist.vendor.hwc.keystone", val) > 0 && |
663 | strcmp(val, "0") != 0) { |
664 | bVal = true; |
665 | } |
666 | if (mKeyStoneMode != bVal) { |
667 | mDisplayRequests |= bVal ? rKeystoneEnable : rKeystoneDisable; |
668 | mKeyStoneMode = bVal; |
669 | } |
670 | } |
671 | } else { |
672 | bVal = false; |
673 | if (sys_get_string_prop("persist.vendor.hwc.keystone", val) > 0 && |
674 | strcmp(val, "0") != 0) { |
675 | bVal = true; |
676 | } |
677 | if (mKeyStoneMode != bVal) { |
678 | mDisplayRequests |= bVal ? |
679 | (rPostProcessorStart | rKeystoneEnable) : rPostProcessorStop; |
680 | mKeyStoneMode = bVal; |
681 | } |
682 | } |
683 | } |
684 | #endif |
685 | /*record and reset requests.*/ |
686 | uint32_t request = mDisplayRequests; |
687 | mDisplayRequests = 0; |
688 | if (request > 0) { |
689 | MESON_LOGE("getDisplayRequest %x", request); |
690 | } |
691 | return request; |
692 | } |
693 | |
694 | int32_t MesonHwc2::handleDisplayRequest(uint32_t request) { |
695 | mDisplayPipe->handleRequest(request); |
696 | return 0; |
697 | } |
698 | |
699 | /**********************Internal Implement********************/ |
700 | |
701 | class MesonHwc2Observer |
702 | : public Hwc2DisplayObserver, public HwcVsyncObserver{ |
703 | public: |
704 | MesonHwc2Observer(hwc2_display_t display, MesonHwc2 * hwc) { |
705 | mDispId = display; |
706 | mHwc = hwc; |
707 | } |
708 | ~MesonHwc2Observer() { |
709 | MESON_LOGD("MesonHwc2Observer disp(%d) destruct.", (int)mDispId); |
710 | } |
711 | |
712 | void refresh() { |
713 | MESON_LOGD("Display (%d) ask for refresh.", (int)mDispId); |
714 | mHwc->refresh(mDispId); |
715 | } |
716 | |
717 | void onVsync(int64_t timestamp) { |
718 | mHwc->onVsync(mDispId, timestamp); |
719 | } |
720 | |
721 | void onHotplug(bool connected) { |
722 | mHwc->onHotplug(mDispId, connected); |
723 | } |
724 | |
725 | protected: |
726 | hwc2_display_t mDispId; |
727 | MesonHwc2 * mHwc; |
728 | }; |
729 | |
730 | MesonHwc2::MesonHwc2() { |
731 | mVirtualDisplayIds = 0; |
732 | mHotplugFn = NULL; |
733 | mHotplugData = NULL; |
734 | mRefreshFn = NULL; |
735 | mRefreshData = NULL; |
736 | mVsyncFn = NULL; |
737 | mVsyncData = NULL; |
738 | mDisplayRequests = 0; |
739 | initialize(); |
740 | } |
741 | |
742 | MesonHwc2::~MesonHwc2() { |
743 | mDisplays.clear(); |
744 | } |
745 | |
746 | void MesonHwc2::refresh(hwc2_display_t display) { |
747 | if (mRefreshFn) { |
748 | mRefreshFn(mRefreshData, display); |
749 | return; |
750 | } |
751 | |
752 | MESON_LOGE("No refresh callback registered."); |
753 | } |
754 | |
755 | void MesonHwc2::onVsync(hwc2_display_t display, int64_t timestamp) { |
756 | if (mVsyncFn) { |
757 | mVsyncFn(mVsyncData, display, timestamp); |
758 | return; |
759 | } |
760 | |
761 | MESON_LOGE("No vsync callback registered."); |
762 | } |
763 | |
764 | void MesonHwc2::onHotplug(hwc2_display_t display, bool connected) { |
765 | if (display == HWC_DISPLAY_PRIMARY && !HwcConfig::primaryHotplugEnabled()) { |
766 | MESON_LOGD("Primary display not support hotplug."); |
767 | return; |
768 | } |
769 | |
770 | hwc2_connection_t connection = |
771 | connected ? HWC2_CONNECTION_CONNECTED : HWC2_CONNECTION_DISCONNECTED; |
772 | |
773 | if (mHotplugFn) { |
774 | MESON_LOGD("On hotplug, Fn: %p, Data: %p, display: %d(%d), connection: %d", |
775 | mHotplugFn, mHotplugData, (int)display, HWC_DISPLAY_PRIMARY, connection); |
776 | mHotplugFn(mHotplugData, display, connection); |
777 | } else { |
778 | MESON_LOGE("No hotplug callback registered."); |
779 | } |
780 | } |
781 | |
782 | int32_t MesonHwc2::captureDisplayScreen(buffer_handle_t hnd) { |
783 | GET_HWC_DISPLAY(0); |
784 | return hwcDisplay->captureDisplayScreen(hnd); |
785 | } |
786 | |
787 | int32_t MesonHwc2::initialize() { |
788 | std::map<uint32_t, std::shared_ptr<HwcDisplay>> mhwcDisps; |
789 | mDisplayPipe = createDisplayPipe(HwcConfig::getPipeline()); |
790 | |
791 | for (uint32_t i = 0; i < HwcConfig::getDisplayNum(); i ++) { |
792 | /*create hwc2display*/ |
793 | auto displayObserver = std::make_shared<MesonHwc2Observer>(i, this); |
794 | auto disp = std::make_shared<Hwc2Display>(displayObserver); |
795 | disp->initialize(); |
796 | mDisplays.emplace(i, disp); |
797 | auto baseDisp = std::dynamic_pointer_cast<HwcDisplay>(disp); |
798 | mhwcDisps.emplace(i, baseDisp); |
799 | } |
800 | |
801 | mDisplayPipe->init(mhwcDisps); |
802 | return HWC2_ERROR_NONE; |
803 | } |
804 | |
805 | bool MesonHwc2::isDisplayValid(hwc2_display_t display) { |
806 | std::map<hwc2_display_t, std::shared_ptr<Hwc2Display>>::iterator it = |
807 | mDisplays.find(display); |
808 | |
809 | if (it != mDisplays.end()) |
810 | return true; |
811 | |
812 | return false; |
813 | } |
814 | |
815 | uint32_t MesonHwc2::getVirtualDisplayId() { |
816 | uint32_t idx; |
817 | for (idx = MESON_VIRTUAL_DISPLAY_ID_START; idx < 31; idx ++) { |
818 | if ((mVirtualDisplayIds & (1 << idx)) == 0) { |
819 | mVirtualDisplayIds |= (1 << idx); |
820 | MESON_LOGD("getVirtualDisplayId (%d) to (%x)", idx, mVirtualDisplayIds); |
821 | return idx; |
822 | } |
823 | } |
824 | |
825 | MESON_LOGE("All virtual display id consumed.\n"); |
826 | return 0; |
827 | } |
828 | |
829 | void MesonHwc2::freeVirtualDisplayId(uint32_t id) { |
830 | mVirtualDisplayIds &= ~(1 << id); |
831 | MESON_LOGD("freeVirtualDisplayId (%d) to (%x)", id, mVirtualDisplayIds); |
832 | } |
833 | |
834 |