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