1 /*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "Display.h"
18
19 #include <sync/sync.h>
20
21 #include <atomic>
22 #include <numeric>
23
24 #include "Device.h"
25
26 namespace android {
27 namespace {
28
29 std::atomic<hwc2_config_t> sNextConfigId{0};
30
IsValidColorMode(android_color_mode_t mode)31 bool IsValidColorMode(android_color_mode_t mode) {
32 switch (mode) {
33 case HAL_COLOR_MODE_NATIVE: // Fall-through
34 case HAL_COLOR_MODE_STANDARD_BT601_625: // Fall-through
35 case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED: // Fall-through
36 case HAL_COLOR_MODE_STANDARD_BT601_525: // Fall-through
37 case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED: // Fall-through
38 case HAL_COLOR_MODE_STANDARD_BT709: // Fall-through
39 case HAL_COLOR_MODE_DCI_P3: // Fall-through
40 case HAL_COLOR_MODE_SRGB: // Fall-through
41 case HAL_COLOR_MODE_ADOBE_RGB: // Fall-through
42 case HAL_COLOR_MODE_DISPLAY_P3:
43 return true;
44 default:
45 return false;
46 }
47 }
48
isValidPowerMode(HWC2::PowerMode mode)49 bool isValidPowerMode(HWC2::PowerMode mode) {
50 switch (mode) {
51 case HWC2::PowerMode::Off: // Fall-through
52 case HWC2::PowerMode::DozeSuspend: // Fall-through
53 case HWC2::PowerMode::Doze: // Fall-through
54 case HWC2::PowerMode::On:
55 return true;
56 default:
57 return false;
58 }
59 }
60
61 } // namespace
62
Display(Device & device,Composer * composer,hwc2_display_t id)63 Display::Display(Device& device, Composer* composer, hwc2_display_t id)
64 : mDevice(device),
65 mComposer(composer),
66 mId(id),
67 mVsyncThread(new VsyncThread(*this)) {}
68
~Display()69 Display::~Display() {}
70
init(uint32_t width,uint32_t height,uint32_t dpiX,uint32_t dpiY,uint32_t refreshRateHz,const std::optional<std::vector<uint8_t>> & edid)71 HWC2::Error Display::init(uint32_t width, uint32_t height, uint32_t dpiX,
72 uint32_t dpiY, uint32_t refreshRateHz,
73 const std::optional<std::vector<uint8_t>>& edid) {
74 ALOGD("%s initializing display:%" PRIu64
75 " width:%d height:%d dpiX:%d dpiY:%d refreshRateHz:%d",
76 __FUNCTION__, mId, width, height, dpiX, dpiY, refreshRateHz);
77
78 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
79
80 mVsyncPeriod = 1000 * 1000 * 1000 / refreshRateHz;
81 mVsyncThread->run("", ANDROID_PRIORITY_URGENT_DISPLAY);
82
83 hwc2_config_t configId = sNextConfigId++;
84
85 Config config(configId);
86 config.setAttribute(HWC2::Attribute::VsyncPeriod, mVsyncPeriod);
87 config.setAttribute(HWC2::Attribute::Width, width);
88 config.setAttribute(HWC2::Attribute::Height, height);
89 config.setAttribute(HWC2::Attribute::DpiX, dpiX * 1000);
90 config.setAttribute(HWC2::Attribute::DpiY, dpiY * 1000);
91 mConfigs.emplace(configId, config);
92
93 mActiveConfigId = configId;
94 mActiveColorMode = HAL_COLOR_MODE_NATIVE;
95 mColorModes.emplace((android_color_mode_t)HAL_COLOR_MODE_NATIVE);
96 mEdid = edid;
97
98 return HWC2::Error::None;
99 }
100
updateParameters(uint32_t width,uint32_t height,uint32_t dpiX,uint32_t dpiY,uint32_t refreshRateHz,const std::optional<std::vector<uint8_t>> & edid)101 HWC2::Error Display::updateParameters(
102 uint32_t width, uint32_t height, uint32_t dpiX, uint32_t dpiY,
103 uint32_t refreshRateHz, const std::optional<std::vector<uint8_t>>& edid) {
104 DEBUG_LOG("%s updating display:%" PRIu64
105 " width:%d height:%d dpiX:%d dpiY:%d refreshRateHz:%d",
106 __FUNCTION__, mId, width, height, dpiX, dpiY, refreshRateHz);
107
108 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
109
110 mVsyncPeriod = 1000 * 1000 * 1000 / refreshRateHz;
111
112 auto it = mConfigs.find(*mActiveConfigId);
113 if (it == mConfigs.end()) {
114 ALOGE("%s: failed to find config %" PRIu32, __func__, *mActiveConfigId);
115 return HWC2::Error::NoResources;
116 }
117 it->second.setAttribute(HWC2::Attribute::VsyncPeriod, mVsyncPeriod);
118 it->second.setAttribute(HWC2::Attribute::Width, width);
119 it->second.setAttribute(HWC2::Attribute::Height, height);
120 it->second.setAttribute(HWC2::Attribute::DpiX, dpiX * 1000);
121 it->second.setAttribute(HWC2::Attribute::DpiY, dpiY * 1000);
122
123 mEdid = edid;
124
125 return HWC2::Error::None;
126 }
127
getLayer(hwc2_layer_t layerId)128 Layer* Display::getLayer(hwc2_layer_t layerId) {
129 auto it = mLayers.find(layerId);
130 if (it == mLayers.end()) {
131 ALOGE("%s Unknown layer:%" PRIu64, __FUNCTION__, layerId);
132 return nullptr;
133 }
134
135 return it->second.get();
136 }
137
waitAndGetClientTargetBuffer()138 buffer_handle_t Display::waitAndGetClientTargetBuffer() {
139 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
140
141 int fence = mClientTarget.getFence();
142 if (fence != -1) {
143 int err = sync_wait(fence, 3000);
144 if (err < 0 && errno == ETIME) {
145 ALOGE("%s waited on fence %" PRId32 " for 3000 ms", __FUNCTION__, fence);
146 }
147 close(fence);
148 }
149
150 return mClientTarget.getBuffer();
151 }
152
acceptChanges()153 HWC2::Error Display::acceptChanges() {
154 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
155
156 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
157
158 if (!mChanges) {
159 ALOGE("%s: display %" PRIu64 " failed, not validated", __FUNCTION__, mId);
160 return HWC2::Error::NotValidated;
161 }
162
163 for (auto& [layerId, layerCompositionType] : mChanges->getTypeChanges()) {
164 auto* layer = getLayer(layerId);
165 if (layer == nullptr) {
166 ALOGE("%s: display:%" PRIu64 " layer:%" PRIu64
167 " dropped before AcceptChanges?",
168 __FUNCTION__, mId, layerId);
169 continue;
170 }
171
172 layer->setCompositionTypeEnum(layerCompositionType);
173 }
174 mChanges->clearTypeChanges();
175
176 return HWC2::Error::None;
177 }
178
createLayer(hwc2_layer_t * outLayerId)179 HWC2::Error Display::createLayer(hwc2_layer_t* outLayerId) {
180 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
181
182 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
183
184 auto layer = std::make_unique<Layer>();
185 auto layerId = layer->getId();
186 DEBUG_LOG("%s created layer:%" PRIu64, __FUNCTION__, layerId);
187
188 *outLayerId = layerId;
189
190 mLayers.emplace(layerId, std::move(layer));
191
192 return HWC2::Error::None;
193 }
194
destroyLayer(hwc2_layer_t layerId)195 HWC2::Error Display::destroyLayer(hwc2_layer_t layerId) {
196 DEBUG_LOG("%s destroy layer:%" PRIu64, __FUNCTION__, layerId);
197
198 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
199
200 auto it = mLayers.find(layerId);
201 if (it == mLayers.end()) {
202 ALOGE("%s display:%" PRIu64 " has no such layer:%." PRIu64, __FUNCTION__,
203 mId, layerId);
204 return HWC2::Error::BadLayer;
205 }
206
207 mOrderedLayers.erase(std::remove_if(mOrderedLayers.begin(), //
208 mOrderedLayers.end(), //
209 [layerId](Layer* layer) {
210 return layer->getId() == layerId;
211 }),
212 mOrderedLayers.end());
213
214 mLayers.erase(it);
215
216 DEBUG_LOG("%s destroyed layer:%" PRIu64, __FUNCTION__, layerId);
217 return HWC2::Error::None;
218 }
219
getActiveConfig(hwc2_config_t * outConfig)220 HWC2::Error Display::getActiveConfig(hwc2_config_t* outConfig) {
221 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
222
223 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
224
225 if (!mActiveConfigId) {
226 ALOGW("%s: display:%" PRIu64 " has no active config.", __FUNCTION__, mId);
227 return HWC2::Error::BadConfig;
228 }
229
230 *outConfig = *mActiveConfigId;
231 return HWC2::Error::None;
232 }
233
getDisplayAttributeEnum(hwc2_config_t configId,HWC2::Attribute attribute,int32_t * outValue)234 HWC2::Error Display::getDisplayAttributeEnum(hwc2_config_t configId,
235 HWC2::Attribute attribute,
236 int32_t* outValue) {
237 auto attributeString = to_string(attribute);
238 DEBUG_LOG("%s: display:%" PRIu64 " attribute:%s", __FUNCTION__, mId,
239 attributeString.c_str());
240
241 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
242
243 auto it = mConfigs.find(configId);
244 if (it == mConfigs.end()) {
245 ALOGW("%s: display:%" PRIu64 "bad config:%" PRIu32, __FUNCTION__, mId,
246 configId);
247 return HWC2::Error::BadConfig;
248 }
249
250 const Config& config = it->second;
251 *outValue = config.getAttribute(attribute);
252 DEBUG_LOG("%s: display:%" PRIu64 " attribute:%s value is %" PRIi32,
253 __FUNCTION__, mId, attributeString.c_str(), *outValue);
254 return HWC2::Error::None;
255 }
256
getDisplayAttribute(hwc2_config_t configId,int32_t attribute,int32_t * outValue)257 HWC2::Error Display::getDisplayAttribute(hwc2_config_t configId,
258 int32_t attribute, int32_t* outValue) {
259 return getDisplayAttributeEnum(
260 configId, static_cast<HWC2::Attribute>(attribute), outValue);
261 }
262
getChangedCompositionTypes(uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outTypes)263 HWC2::Error Display::getChangedCompositionTypes(uint32_t* outNumElements,
264 hwc2_layer_t* outLayers,
265 int32_t* outTypes) {
266 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
267
268 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
269
270 if (!mChanges) {
271 ALOGE("%s: for display:%" PRIu64 " failed, display not validated",
272 __FUNCTION__, mId);
273 return HWC2::Error::NotValidated;
274 }
275
276 if ((outLayers == nullptr) || (outTypes == nullptr)) {
277 *outNumElements = mChanges->getTypeChanges().size();
278 return HWC2::Error::None;
279 }
280
281 uint32_t numWritten = 0;
282 for (const auto& element : mChanges->getTypeChanges()) {
283 if (numWritten == *outNumElements) {
284 break;
285 }
286
287 auto layerId = element.first;
288 const auto layerCompositionType = element.second;
289 const auto layerCompositionTypeString = to_string(layerCompositionType);
290 DEBUG_LOG("%s: display:%" PRIu64 " layer:%" PRIu64 " changed to %s",
291 __FUNCTION__, mId, layerId, layerCompositionTypeString.c_str());
292
293 outLayers[numWritten] = layerId;
294 outTypes[numWritten] = static_cast<int32_t>(layerCompositionType);
295 ++numWritten;
296 }
297 *outNumElements = numWritten;
298 return HWC2::Error::None;
299 }
300
getColorModes(uint32_t * outNumModes,int32_t * outModes)301 HWC2::Error Display::getColorModes(uint32_t* outNumModes, int32_t* outModes) {
302 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
303
304 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
305
306 if (!outModes) {
307 *outNumModes = mColorModes.size();
308 return HWC2::Error::None;
309 }
310
311 // we only support HAL_COLOR_MODE_NATIVE so far
312 uint32_t numModes = std::min<uint32_t>(
313 *outNumModes, static_cast<uint32_t>(mColorModes.size()));
314 std::copy_n(mColorModes.cbegin(), numModes, outModes);
315 *outNumModes = numModes;
316 return HWC2::Error::None;
317 }
318
getConfigs(uint32_t * outNumConfigs,hwc2_config_t * outConfigs)319 HWC2::Error Display::getConfigs(uint32_t* outNumConfigs,
320 hwc2_config_t* outConfigs) {
321 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
322
323 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
324
325 if (!outConfigs) {
326 *outNumConfigs = mConfigs.size();
327 return HWC2::Error::None;
328 }
329
330 uint32_t numWritten = 0;
331 for (const auto& [configId, config] : mConfigs) {
332 if (numWritten == *outNumConfigs) {
333 break;
334 }
335 outConfigs[numWritten] = configId;
336 ++numWritten;
337 }
338
339 *outNumConfigs = numWritten;
340 return HWC2::Error::None;
341 }
342
getDozeSupport(int32_t * outSupport)343 HWC2::Error Display::getDozeSupport(int32_t* outSupport) {
344 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
345
346 // We don't support so far
347 *outSupport = 0;
348 return HWC2::Error::None;
349 }
350
getHdrCapabilities(uint32_t * outNumTypes,int32_t *,float *,float *,float *)351 HWC2::Error Display::getHdrCapabilities(uint32_t* outNumTypes,
352 int32_t* /*outTypes*/,
353 float* /*outMaxLuminance*/,
354 float* /*outMaxAverageLuminance*/,
355 float* /*outMinLuminance*/) {
356 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
357
358 // We don't support so far
359 *outNumTypes = 0;
360 return HWC2::Error::None;
361 }
362
getName(uint32_t * outSize,char * outName)363 HWC2::Error Display::getName(uint32_t* outSize, char* outName) {
364 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
365
366 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
367
368 if (!outName) {
369 *outSize = mName.size();
370 return HWC2::Error::None;
371 }
372 auto numCopied = mName.copy(outName, *outSize);
373 *outSize = numCopied;
374 return HWC2::Error::None;
375 }
376
addReleaseFenceLocked(int32_t fence)377 HWC2::Error Display::addReleaseFenceLocked(int32_t fence) {
378 DEBUG_LOG("%s: display:%" PRIu64 " fence:%d", __FUNCTION__, mId, fence);
379
380 mReleaseFences.push_back(fence);
381 return HWC2::Error::None;
382 }
383
addReleaseLayerLocked(hwc2_layer_t layerId)384 HWC2::Error Display::addReleaseLayerLocked(hwc2_layer_t layerId) {
385 DEBUG_LOG("%s: display:%" PRIu64 " layer:%" PRIu64, __FUNCTION__, mId,
386 layerId);
387
388 mReleaseLayerIds.push_back(layerId);
389 return HWC2::Error::None;
390 }
391
getReleaseFences(uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outFences)392 HWC2::Error Display::getReleaseFences(uint32_t* outNumElements,
393 hwc2_layer_t* outLayers,
394 int32_t* outFences) {
395 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
396
397 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
398
399 *outNumElements = mReleaseLayerIds.size();
400
401 if (*outNumElements && outLayers) {
402 DEBUG_LOG("%s export release layers", __FUNCTION__);
403 memcpy(outLayers, mReleaseLayerIds.data(),
404 sizeof(hwc2_layer_t) * (*outNumElements));
405 }
406
407 if (*outNumElements && outFences) {
408 DEBUG_LOG("%s export release fences", __FUNCTION__);
409 memcpy(outFences, mReleaseFences.data(),
410 sizeof(int32_t) * (*outNumElements));
411 }
412
413 return HWC2::Error::None;
414 }
415
clearReleaseFencesAndIdsLocked()416 HWC2::Error Display::clearReleaseFencesAndIdsLocked() {
417 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
418
419 mReleaseLayerIds.clear();
420 mReleaseFences.clear();
421
422 return HWC2::Error::None;
423 }
424
getRequests(int32_t * outDisplayRequests,uint32_t * outNumElements,hwc2_layer_t * outLayers,int32_t * outLayerRequests)425 HWC2::Error Display::getRequests(int32_t* outDisplayRequests,
426 uint32_t* outNumElements,
427 hwc2_layer_t* outLayers,
428 int32_t* outLayerRequests) {
429 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
430
431 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
432
433 if (!mChanges) {
434 return HWC2::Error::NotValidated;
435 }
436
437 if (outLayers == nullptr || outLayerRequests == nullptr) {
438 *outNumElements = mChanges->getNumLayerRequests();
439 return HWC2::Error::None;
440 }
441
442 // TODO
443 // Display requests (HWC2::DisplayRequest) are not supported so far:
444 *outDisplayRequests = 0;
445
446 uint32_t numWritten = 0;
447 for (const auto& request : mChanges->getLayerRequests()) {
448 if (numWritten == *outNumElements) {
449 break;
450 }
451 outLayers[numWritten] = request.first;
452 outLayerRequests[numWritten] = static_cast<int32_t>(request.second);
453 ++numWritten;
454 }
455
456 return HWC2::Error::None;
457 }
458
getType(int32_t * outType)459 HWC2::Error Display::getType(int32_t* outType) {
460 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
461
462 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
463
464 *outType = (int32_t)mType;
465 return HWC2::Error::None;
466 }
467
present(int32_t * outRetireFence)468 HWC2::Error Display::present(int32_t* outRetireFence) {
469 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
470
471 *outRetireFence = -1;
472
473 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
474
475 if (!mChanges || (mChanges->getNumTypes() > 0)) {
476 ALOGE("%s: display:%" PRIu64 " failed, not validated", __FUNCTION__, mId);
477 return HWC2::Error::NotValidated;
478 }
479 mChanges.reset();
480
481 if (mComposer == nullptr) {
482 ALOGE("%s: display:%" PRIu64 " missing composer", __FUNCTION__, mId);
483 return HWC2::Error::NoResources;
484 }
485
486 HWC2::Error error = mComposer->presentDisplay(this, outRetireFence);
487 if (error != HWC2::Error::None) {
488 ALOGE("%s: display:%" PRIu64 " failed to present", __FUNCTION__, mId);
489 return error;
490 }
491
492 DEBUG_LOG("%s: display:%" PRIu64 " present done!", __FUNCTION__, mId);
493 return HWC2::Error::None;
494 }
495
setActiveConfig(hwc2_config_t configId)496 HWC2::Error Display::setActiveConfig(hwc2_config_t configId) {
497 DEBUG_LOG("%s: display:%" PRIu64 " setting active config to %" PRIu32,
498 __FUNCTION__, mId, configId);
499
500 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
501
502 if (mConfigs.find(configId) == mConfigs.end()) {
503 ALOGE("%s: display:%" PRIu64 " bad config:%" PRIu32, __FUNCTION__, mId,
504 configId);
505 return HWC2::Error::BadConfig;
506 }
507
508 mActiveConfigId = configId;
509 return HWC2::Error::None;
510 }
511
setClientTarget(buffer_handle_t target,int32_t acquireFence,int32_t,hwc_region_t)512 HWC2::Error Display::setClientTarget(buffer_handle_t target,
513 int32_t acquireFence,
514 int32_t /*dataspace*/,
515 hwc_region_t /*damage*/) {
516 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
517
518 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
519 mClientTarget.setBuffer(target);
520 mClientTarget.setFence(acquireFence);
521 mComposer->onDisplayClientTargetSet(this);
522 return HWC2::Error::None;
523 }
524
setColorMode(int32_t intMode)525 HWC2::Error Display::setColorMode(int32_t intMode) {
526 DEBUG_LOG("%s: display:%" PRIu64 " setting color mode to %" PRId32,
527 __FUNCTION__, mId, intMode);
528
529 auto mode = static_cast<android_color_mode_t>(intMode);
530 if (!IsValidColorMode(mode)) {
531 ALOGE("%s: display:%" PRIu64 " invalid color mode %" PRId32, __FUNCTION__,
532 mId, intMode);
533 return HWC2::Error::BadParameter;
534 }
535
536 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
537
538 if (mColorModes.count(mode) == 0) {
539 ALOGE("%s: display %" PRIu64 " mode %d not found", __FUNCTION__, mId,
540 intMode);
541 return HWC2::Error::Unsupported;
542 }
543 mActiveColorMode = mode;
544 return HWC2::Error::None;
545 }
546
setColorTransform(const float *,int32_t hint)547 HWC2::Error Display::setColorTransform(const float* /*matrix*/, int32_t hint) {
548 DEBUG_LOG("%s: display:%" PRIu64 " setting hint to %d", __FUNCTION__, mId,
549 hint);
550
551 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
552 // we force client composition if this is set
553 if (hint == 0) {
554 mSetColorTransform = false;
555 } else {
556 mSetColorTransform = true;
557 }
558 return HWC2::Error::None;
559 }
560
setOutputBuffer(buffer_handle_t,int32_t)561 HWC2::Error Display::setOutputBuffer(buffer_handle_t /*buffer*/,
562 int32_t /*releaseFence*/) {
563 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
564 // TODO: for virtual display
565 return HWC2::Error::None;
566 }
567
setPowerMode(int32_t intMode)568 HWC2::Error Display::setPowerMode(int32_t intMode) {
569 auto mode = static_cast<HWC2::PowerMode>(intMode);
570 auto modeString = to_string(mode);
571 DEBUG_LOG("%s: display:%" PRIu64 " setting power mode to %s", __FUNCTION__,
572 mId, modeString.c_str());
573
574 if (!isValidPowerMode(mode)) {
575 return HWC2::Error::BadParameter;
576 }
577
578 if (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend) {
579 ALOGE("%s display %" PRIu64 " power mode %s not supported", __FUNCTION__,
580 mId, modeString.c_str());
581 return HWC2::Error::Unsupported;
582 }
583
584 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
585
586 mPowerMode = mode;
587 return HWC2::Error::None;
588 }
589
setVsyncEnabled(int32_t intEnable)590 HWC2::Error Display::setVsyncEnabled(int32_t intEnable) {
591 auto enable = static_cast<HWC2::Vsync>(intEnable);
592 auto enableString = to_string(enable);
593 DEBUG_LOG("%s: display:%" PRIu64 " setting vsync to %s", __FUNCTION__, mId,
594 enableString.c_str());
595
596 if (enable == HWC2::Vsync::Invalid) {
597 return HWC2::Error::BadParameter;
598 }
599
600 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
601 DEBUG_LOG("%s: display:%" PRIu64 " setting vsync locked to %s", __FUNCTION__,
602 mId, enableString.c_str());
603
604 mVsyncEnabled = enable;
605 return HWC2::Error::None;
606 }
607
setVsyncPeriod(uint32_t period)608 HWC2::Error Display::setVsyncPeriod(uint32_t period) {
609 DEBUG_LOG("%s: display:%" PRIu64 " setting vsync period to %d", __FUNCTION__,
610 mId, period);
611
612 mVsyncPeriod = period;
613 return HWC2::Error::None;
614 }
615
validate(uint32_t * outNumTypes,uint32_t * outNumRequests)616 HWC2::Error Display::validate(uint32_t* outNumTypes, uint32_t* outNumRequests) {
617 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
618
619 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
620
621 mOrderedLayers.clear();
622 mOrderedLayers.reserve(mLayers.size());
623 for (auto& [_, layerPtr] : mLayers) {
624 mOrderedLayers.push_back(layerPtr.get());
625 }
626
627 std::sort(mOrderedLayers.begin(), mOrderedLayers.end(),
628 [](const Layer* layerA, const Layer* layerB) {
629 const auto zA = layerA->getZ();
630 const auto zB = layerB->getZ();
631 if (zA != zB) {
632 return zA < zB;
633 }
634 return layerA->getId() < layerB->getId();
635 });
636
637 if (!mChanges) {
638 mChanges.reset(new Changes);
639 } else {
640 ALOGE("Validate was called more than once!");
641 }
642
643 if (mComposer == nullptr) {
644 ALOGE("%s: display:%" PRIu64 " missing composer", __FUNCTION__, mId);
645 return HWC2::Error::NoResources;
646 }
647
648 std::unordered_map<hwc2_layer_t, HWC2::Composition> changes;
649
650 HWC2::Error error = mComposer->validateDisplay(this, &changes);
651 if (error != HWC2::Error::None) {
652 ALOGE("%s: display:%" PRIu64 " failed to validate", __FUNCTION__, mId);
653 return error;
654 }
655
656 for (const auto& [layerId, changedCompositionType] : changes) {
657 mChanges->addTypeChange(layerId, changedCompositionType);
658 }
659
660 *outNumTypes = mChanges->getNumTypes();
661 *outNumRequests = mChanges->getNumLayerRequests();
662 return *outNumTypes > 0 ? HWC2::Error::HasChanges : HWC2::Error::None;
663 }
664
updateLayerZ(hwc2_layer_t layerId,uint32_t z)665 HWC2::Error Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) {
666 DEBUG_LOG("%s: display:%" PRIu64 " update layer:%" PRIu64 " z:%d",
667 __FUNCTION__, mId, layerId, z);
668
669 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
670
671 const auto layerIt = mLayers.find(layerId);
672 if (layerIt == mLayers.end()) {
673 ALOGE("%s failed to find layer %" PRIu64, __FUNCTION__, layerId);
674 return HWC2::Error::BadLayer;
675 }
676
677 auto& layer = layerIt->second;
678 layer->setZ(z);
679 return HWC2::Error::None;
680 }
681
getClientTargetSupport(uint32_t width,uint32_t height,int32_t format,int32_t dataspace)682 HWC2::Error Display::getClientTargetSupport(uint32_t width, uint32_t height,
683 int32_t format, int32_t dataspace) {
684 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
685 std::unique_lock<std::recursive_mutex> lock(mStateMutex);
686
687 if (!mActiveConfigId) {
688 return HWC2::Error::Unsupported;
689 }
690
691 const auto it = mConfigs.find(*mActiveConfigId);
692 if (it == mConfigs.end()) {
693 ALOGE("%s failed to find active config:%" PRIu32, __FUNCTION__,
694 *mActiveConfigId);
695 return HWC2::Error::Unsupported;
696 }
697
698 const Config& activeConfig = it->second;
699 const uint32_t activeConfigWidth =
700 static_cast<uint32_t>(activeConfig.getAttribute(HWC2::Attribute::Width));
701 const uint32_t activeConfigHeight =
702 static_cast<uint32_t>(activeConfig.getAttribute(HWC2::Attribute::Height));
703 if (width == activeConfigWidth && height == activeConfigHeight &&
704 format == HAL_PIXEL_FORMAT_RGBA_8888 &&
705 dataspace == HAL_DATASPACE_UNKNOWN) {
706 return HWC2::Error::None;
707 }
708
709 return HWC2::Error::None;
710 }
711
712 // thess EDIDs are carefully generated according to the EDID spec version 1.3,
713 // more info can be found from the following file:
714 // frameworks/native/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
715 // approved pnp ids can be found here: https://uefi.org/pnp_id_list
716 // pnp id: GGL, name: EMU_display_0, last byte is checksum
717 // display id is local:8141603649153536
718 static const uint8_t sEDID0[] = {
719 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00,
720 0x01, 0x00, 0x00, 0x00, 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78,
721 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27, 0x12, 0x48, 0x4c, 0x00,
722 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
723 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
724 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0xfc, 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73,
729 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x30, 0x00, 0x4b};
730
731 // pnp id: GGL, name: EMU_display_1
732 // display id is local:8140900251843329
733 static const uint8_t sEDID1[] = {
734 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00,
735 0x01, 0x00, 0x00, 0x00, 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78,
736 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27, 0x12, 0x48, 0x4c, 0x00,
737 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
738 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
739 0x2d, 0x40, 0x58, 0x2c, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
743 0x00, 0x00, 0x00, 0xfc, 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73,
744 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x31, 0x00, 0x3b};
745
746 // pnp id: GGL, name: EMU_display_2
747 // display id is local:8140940453066754
748 static const uint8_t sEDID2[] = {
749 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00,
750 0x01, 0x00, 0x00, 0x00, 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78,
751 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27, 0x12, 0x48, 0x4c, 0x00,
752 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
753 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
754 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758 0x00, 0x00, 0x00, 0xfc, 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73,
759 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x32, 0x00, 0x49};
760
761 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
762
getDisplayIdentificationData(uint8_t * outPort,uint32_t * outDataSize,uint8_t * outData)763 HWC2::Error Display::getDisplayIdentificationData(uint8_t* outPort,
764 uint32_t* outDataSize,
765 uint8_t* outData) {
766 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
767
768 if (outPort == nullptr || outDataSize == nullptr) {
769 return HWC2::Error::BadParameter;
770 }
771
772 if (mEdid) {
773 if (outData) {
774 *outDataSize = std::min<uint32_t>(*outDataSize, (*mEdid).size());
775 memcpy(outData, (*mEdid).data(), *outDataSize);
776 } else {
777 *outDataSize = (*mEdid).size();
778 }
779 *outPort = mId;
780 return HWC2::Error::None;
781 }
782
783 // fallback to legacy EDID implementation
784 uint32_t len = std::min(*outDataSize, (uint32_t)ARRAY_SIZE(sEDID0));
785 if (outData != nullptr && len < (uint32_t)ARRAY_SIZE(sEDID0)) {
786 ALOGW("%s: display:%" PRIu64 " small buffer size: %u is specified",
787 __FUNCTION__, mId, len);
788 }
789 *outDataSize = ARRAY_SIZE(sEDID0);
790 switch (mId) {
791 case 0:
792 *outPort = 0;
793 if (outData) memcpy(outData, sEDID0, len);
794 break;
795
796 case 1:
797 *outPort = 1;
798 if (outData) memcpy(outData, sEDID1, len);
799 break;
800
801 case 2:
802 *outPort = 2;
803 if (outData) memcpy(outData, sEDID2, len);
804 break;
805
806 default:
807 *outPort = (uint8_t)mId;
808 if (outData) {
809 memcpy(outData, sEDID2, len);
810 uint32_t size = ARRAY_SIZE(sEDID0);
811 // change the name to EMU_display_<mID>
812 // note the 3rd char from back is the number, _0, _1, _2, etc.
813 if (len >= size - 2) outData[size - 3] = '0' + (uint8_t)mId;
814 if (len >= size) {
815 // update the last byte, which is checksum byte
816 uint8_t checksum = -(uint8_t)std::accumulate(
817 outData, outData + size - 1, static_cast<uint8_t>(0));
818 outData[size - 1] = checksum;
819 }
820 }
821 break;
822 }
823
824 return HWC2::Error::None;
825 }
826
getDisplayCapabilities(uint32_t * outNumCapabilities,uint32_t * outCapabilities)827 HWC2::Error Display::getDisplayCapabilities(uint32_t* outNumCapabilities,
828 uint32_t* outCapabilities) {
829 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
830 if (outNumCapabilities == nullptr) {
831 return HWC2::Error::None;
832 }
833
834 bool brightness_support = false;
835 bool doze_support = false;
836
837 uint32_t count = 1 + (doze_support ? 1 : 0) + (brightness_support ? 1 : 0);
838 int index = 0;
839 if (outCapabilities != nullptr && (*outNumCapabilities >= count)) {
840 outCapabilities[index++] =
841 HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
842 if (doze_support) {
843 outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE;
844 }
845 if (brightness_support) {
846 outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_BRIGHTNESS;
847 }
848 }
849
850 *outNumCapabilities = count;
851 return HWC2::Error::None;
852 }
853
getDisplayBrightnessSupport(bool * out_support)854 HWC2::Error Display::getDisplayBrightnessSupport(bool* out_support) {
855 DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
856
857 *out_support = false;
858 return HWC2::Error::None;
859 }
860
setDisplayBrightness(float brightness)861 HWC2::Error Display::setDisplayBrightness(float brightness) {
862 DEBUG_LOG("%s: display:%" PRIu64 " brightness %f", __FUNCTION__, mId,
863 brightness);
864
865 ALOGW("TODO: setDisplayBrightness() is not implemented yet: brightness=%f",
866 brightness);
867 return HWC2::Error::Unsupported;
868 }
869
setAttribute(HWC2::Attribute attribute,int32_t value)870 void Display::Config::setAttribute(HWC2::Attribute attribute, int32_t value) {
871 mAttributes[attribute] = value;
872 }
873
getAttribute(HWC2::Attribute attribute) const874 int32_t Display::Config::getAttribute(HWC2::Attribute attribute) const {
875 if (mAttributes.count(attribute) == 0) {
876 return -1;
877 }
878 return mAttributes.at(attribute);
879 }
880
toString() const881 std::string Display::Config::toString() const {
882 std::string output;
883
884 auto widthIt = mAttributes.find(HWC2::Attribute::Width);
885 if (widthIt != mAttributes.end()) {
886 output += " w:" + std::to_string(widthIt->second);
887 }
888
889 auto heightIt = mAttributes.find(HWC2::Attribute::Height);
890 if (heightIt != mAttributes.end()) {
891 output += " h:" + std::to_string(heightIt->second);
892 }
893
894 auto vsyncIt = mAttributes.find(HWC2::Attribute::VsyncPeriod);
895 if (vsyncIt != mAttributes.end()) {
896 output += " vsync:" + std::to_string(1e9 / vsyncIt->second);
897 }
898
899 auto dpiXIt = mAttributes.find(HWC2::Attribute::DpiX);
900 if (dpiXIt != mAttributes.end()) {
901 output += " dpi-x:" + std::to_string(dpiXIt->second / 1000.0f);
902 }
903
904 auto dpiYIt = mAttributes.find(HWC2::Attribute::DpiY);
905 if (dpiYIt != mAttributes.end()) {
906 output += " dpi-y:" + std::to_string(dpiYIt->second / 1000.0f);
907 }
908
909 return output;
910 }
911
912 // VsyncThread function
threadLoop()913 bool Display::VsyncThread::threadLoop() {
914 struct timespec rt;
915 if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
916 ALOGE("%s: error in vsync thread clock_gettime: %s", __FUNCTION__,
917 strerror(errno));
918 return true;
919 }
920 const int logInterval = 60;
921 int64_t lastLogged = rt.tv_sec;
922 int sent = 0;
923 int lastSent = 0;
924 bool vsyncEnabled = false;
925
926 struct timespec wait_time;
927 wait_time.tv_sec = 0;
928 wait_time.tv_nsec = mDisplay.mVsyncPeriod;
929 const int64_t kOneRefreshNs = mDisplay.mVsyncPeriod;
930 const int64_t kOneSecondNs = 1000ULL * 1000ULL * 1000ULL;
931 int64_t lastTimeNs = -1;
932 int64_t phasedWaitNs = 0;
933 int64_t currentNs = 0;
934
935 while (true) {
936 clock_gettime(CLOCK_MONOTONIC, &rt);
937 currentNs = rt.tv_nsec + rt.tv_sec * kOneSecondNs;
938
939 if (lastTimeNs < 0) {
940 phasedWaitNs = currentNs + kOneRefreshNs;
941 } else {
942 phasedWaitNs =
943 kOneRefreshNs * ((currentNs - lastTimeNs) / kOneRefreshNs + 1) +
944 lastTimeNs;
945 }
946
947 wait_time.tv_sec = phasedWaitNs / kOneSecondNs;
948 wait_time.tv_nsec = phasedWaitNs - wait_time.tv_sec * kOneSecondNs;
949
950 int ret;
951 do {
952 ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wait_time, NULL);
953 } while (ret == -1 && errno == EINTR);
954
955 lastTimeNs = phasedWaitNs;
956
957 std::unique_lock<std::recursive_mutex> lock(mDisplay.mStateMutex);
958 vsyncEnabled = (mDisplay.mVsyncEnabled == HWC2::Vsync::Enable);
959 lock.unlock();
960
961 if (!vsyncEnabled) {
962 continue;
963 }
964
965 lock.lock();
966 const auto& callbackInfo =
967 mDisplay.mDevice.mCallbacks[HWC2::Callback::Vsync];
968 auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer);
969 lock.unlock();
970
971 if (vsync) {
972 DEBUG_LOG("%s: display:%" PRIu64 " calling vsync", __FUNCTION__,
973 mDisplay.mId);
974 vsync(callbackInfo.data, mDisplay.mId, lastTimeNs);
975 }
976
977 int64_t lastSentInterval = rt.tv_sec - lastLogged;
978 if (lastSentInterval >= logInterval) {
979 DEBUG_LOG("sent %d syncs in %" PRId64 "s", sent - lastSent,
980 lastSentInterval);
981 lastLogged = rt.tv_sec;
982 lastSent = sent;
983 }
984 ++sent;
985 }
986 return false;
987 }
988
989 } // namespace android
990