1 /*
2 * Copyright 2022 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 "HostFrameComposer.h"
18
19 #include <EGL/egl.h>
20 #include <EGL/eglext.h>
21 #include <android-base/parseint.h>
22 #include <android-base/properties.h>
23 #include <android-base/strings.h>
24 #include <android-base/unique_fd.h>
25 #include <hardware/hwcomposer2.h>
26 #include <poll.h>
27 #include <sync/sync.h>
28 #include <ui/GraphicBuffer.h>
29
30 #include <optional>
31 #include <tuple>
32
33 #include "Display.h"
34 #include "HostUtils.h"
35 #include "Sync.h"
36 #include "gfxstream/guest/goldfish_sync.h"
37 #include "virtgpu_drm.h"
38
39 namespace aidl::android::hardware::graphics::composer3::impl {
40 namespace {
41
AsHwcRect(const common::Rect & rect)42 hwc_rect AsHwcRect(const common::Rect& rect) {
43 hwc_rect out;
44 out.left = rect.left;
45 out.top = rect.top;
46 out.right = rect.right;
47 out.bottom = rect.bottom;
48 return out;
49 }
50
AsHwcFrect(const common::FRect & rect)51 hwc_frect AsHwcFrect(const common::FRect& rect) {
52 hwc_frect out;
53 out.left = rect.left;
54 out.top = rect.top;
55 out.right = rect.right;
56 out.bottom = rect.bottom;
57 return out;
58 }
59
AsHwcColor(const Color & color)60 hwc_color AsHwcColor(const Color& color) {
61 hwc_color out;
62 out.r = static_cast<uint8_t>(color.r * 255.0f);
63 out.g = static_cast<uint8_t>(color.g * 255.0f);
64 out.b = static_cast<uint8_t>(color.b * 255.0f);
65 out.a = static_cast<uint8_t>(color.a * 255.0f);
66 return out;
67 }
68
AsHwcTransform(const common::Transform & transform)69 hwc_transform_t AsHwcTransform(const common::Transform& transform) {
70 switch (transform) {
71 case common::Transform::NONE:
72 return static_cast<hwc_transform_t>(0);
73 case common::Transform::FLIP_H:
74 return HWC_TRANSFORM_FLIP_H;
75 case common::Transform::FLIP_V:
76 return HWC_TRANSFORM_FLIP_V;
77 case common::Transform::ROT_90:
78 return HWC_TRANSFORM_ROT_90;
79 case common::Transform::ROT_180:
80 return HWC_TRANSFORM_ROT_180;
81 case common::Transform::ROT_270:
82 return HWC_TRANSFORM_ROT_270;
83 }
84 }
85
isMinigbmFromProperty()86 static bool isMinigbmFromProperty() {
87 static constexpr const auto kGrallocProp = "ro.hardware.gralloc";
88
89 const auto grallocProp = ::android::base::GetProperty(kGrallocProp, "");
90 DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, grallocProp.c_str());
91
92 if (grallocProp == "minigbm") {
93 DEBUG_LOG("%s: Using minigbm, in minigbm mode.\n", __FUNCTION__);
94 return true;
95 } else {
96 DEBUG_LOG("%s: Is not using minigbm, in goldfish mode.\n", __FUNCTION__);
97 return false;
98 }
99 }
100
101 typedef struct compose_layer {
102 uint32_t cbHandle;
103 hwc2_composition_t composeMode;
104 hwc_rect_t displayFrame;
105 hwc_frect_t crop;
106 int32_t blendMode;
107 float alpha;
108 hwc_color_t color;
109 hwc_transform_t transform;
110 } ComposeLayer;
111
112 typedef struct compose_device {
113 uint32_t version;
114 uint32_t targetHandle;
115 uint32_t numLayers;
116 struct compose_layer layer[0];
117 } ComposeDevice;
118
119 typedef struct compose_device_v2 {
120 uint32_t version;
121 uint32_t displayId;
122 uint32_t targetHandle;
123 uint32_t numLayers;
124 struct compose_layer layer[0];
125 } ComposeDevice_v2;
126
127 class ComposeMsg {
128 public:
ComposeMsg(uint32_t layerCnt=0)129 ComposeMsg(uint32_t layerCnt = 0)
130 : mData(sizeof(ComposeDevice) + layerCnt * sizeof(ComposeLayer)) {
131 mComposeDevice = reinterpret_cast<ComposeDevice*>(mData.data());
132 mLayerCnt = layerCnt;
133 }
134
get()135 ComposeDevice* get() { return mComposeDevice; }
136
getLayerCnt()137 uint32_t getLayerCnt() { return mLayerCnt; }
138
139 private:
140 std::vector<uint8_t> mData;
141 uint32_t mLayerCnt;
142 ComposeDevice* mComposeDevice;
143 };
144
145 class ComposeMsg_v2 {
146 public:
ComposeMsg_v2(uint32_t layerCnt=0)147 ComposeMsg_v2(uint32_t layerCnt = 0)
148 : mData(sizeof(ComposeDevice_v2) + layerCnt * sizeof(ComposeLayer)) {
149 mComposeDevice = reinterpret_cast<ComposeDevice_v2*>(mData.data());
150 mLayerCnt = layerCnt;
151 }
152
get()153 ComposeDevice_v2* get() { return mComposeDevice; }
154
getLayerCnt()155 uint32_t getLayerCnt() { return mLayerCnt; }
156
157 private:
158 std::vector<uint8_t> mData;
159 uint32_t mLayerCnt;
160 ComposeDevice_v2* mComposeDevice;
161 };
162
163 } // namespace
164
init()165 HWC3::Error HostFrameComposer::init() {
166 mIsMinigbm = isMinigbmFromProperty();
167
168 if (mIsMinigbm) {
169 mDrmClient.emplace();
170
171 HWC3::Error error = mDrmClient->init();
172 if (error != HWC3::Error::None) {
173 ALOGE("%s: failed to initialize DrmClient", __FUNCTION__);
174 return error;
175 }
176
177 mSyncHelper.reset(gfxstream::createPlatformSyncHelper());
178 } else {
179 mSyncDeviceFd = goldfish_sync_open();
180 }
181
182 return HWC3::Error::None;
183 }
184
registerOnHotplugCallback(const HotplugCallback & cb)185 HWC3::Error HostFrameComposer::registerOnHotplugCallback(const HotplugCallback& cb) {
186 if (mDrmClient) {
187 mDrmClient->registerOnHotplugCallback(cb);
188 }
189 return HWC3::Error::None;
190 }
191
unregisterOnHotplugCallback()192 HWC3::Error HostFrameComposer::unregisterOnHotplugCallback() {
193 if (mDrmClient) {
194 mDrmClient->unregisterOnHotplugCallback();
195 }
196 return HWC3::Error::None;
197 }
198
createHostComposerDisplayInfo(Display * display,uint32_t hostDisplayId)199 HWC3::Error HostFrameComposer::createHostComposerDisplayInfo(Display* display,
200 uint32_t hostDisplayId) {
201 HWC3::Error error = HWC3::Error::None;
202
203 int64_t displayId = display->getId();
204 int32_t displayConfigId;
205 int32_t displayWidth;
206 int32_t displayHeight;
207
208 error = display->getActiveConfig(&displayConfigId);
209 if (error != HWC3::Error::None) {
210 ALOGE("%s: display:%" PRIu64 " has no active config", __FUNCTION__, displayId);
211 return error;
212 }
213
214 error = display->getDisplayAttribute(displayConfigId, DisplayAttribute::WIDTH, &displayWidth);
215 if (error != HWC3::Error::None) {
216 ALOGE("%s: display:%" PRIu64 " failed to get width", __FUNCTION__, displayId);
217 return error;
218 }
219
220 error = display->getDisplayAttribute(displayConfigId, DisplayAttribute::HEIGHT, &displayHeight);
221 if (error != HWC3::Error::None) {
222 ALOGE("%s: display:%" PRIu64 " failed to get height", __FUNCTION__, displayId);
223 return error;
224 }
225
226 HostComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
227
228 displayInfo.hostDisplayId = hostDisplayId;
229 displayInfo.swapchain = DrmSwapchain::create(
230 static_cast<uint32_t>(displayWidth), static_cast<uint32_t>(displayHeight),
231 ::android::GraphicBuffer::USAGE_HW_COMPOSER | ::android::GraphicBuffer::USAGE_HW_RENDER,
232 mDrmClient ? &mDrmClient.value() : nullptr);
233 if (!displayInfo.swapchain) {
234 ALOGE("%s: display:%" PRIu64 " failed to allocate swapchain", __FUNCTION__, displayId);
235 return HWC3::Error::NoResources;
236 }
237 return HWC3::Error::None;
238 }
239
onDisplayCreate(Display * display)240 HWC3::Error HostFrameComposer::onDisplayCreate(Display* display) {
241 HWC3::Error error = HWC3::Error::None;
242
243 const uint32_t displayId = static_cast<uint32_t>(display->getId());
244 int32_t displayConfigId;
245 int32_t displayWidth;
246 int32_t displayHeight;
247 int32_t displayDpiX;
248
249 error = display->getActiveConfig(&displayConfigId);
250 if (error != HWC3::Error::None) {
251 ALOGE("%s: display:%" PRIu32 " has no active config", __FUNCTION__, displayId);
252 return error;
253 }
254
255 error = display->getDisplayAttribute(displayConfigId, DisplayAttribute::WIDTH, &displayWidth);
256 if (error != HWC3::Error::None) {
257 ALOGE("%s: display:%" PRIu32 " failed to get width", __FUNCTION__, displayId);
258 return error;
259 }
260
261 error = display->getDisplayAttribute(displayConfigId, DisplayAttribute::HEIGHT, &displayHeight);
262 if (error != HWC3::Error::None) {
263 ALOGE("%s: display:%" PRIu32 " failed to get height", __FUNCTION__, displayId);
264 return error;
265 }
266
267 error = display->getDisplayAttribute(displayConfigId, DisplayAttribute::DPI_X, &displayDpiX);
268 if (error != HWC3::Error::None) {
269 ALOGE("%s: display:%" PRIu32 " failed to get height", __FUNCTION__, displayId);
270 return error;
271 }
272
273 uint32_t hostDisplayId = 0;
274
275 DEFINE_AND_VALIDATE_HOST_CONNECTION
276 if (displayId == 0) {
277 // Primary display:
278 hostCon->lock();
279 if (rcEnc->rcCreateDisplayById(rcEnc, displayId)) {
280 ALOGE("%s host failed to create display %" PRIu32, __func__, displayId);
281 hostCon->unlock();
282 return HWC3::Error::NoResources;
283 }
284 if (rcEnc->rcSetDisplayPoseDpi(
285 rcEnc, displayId, -1, -1, static_cast<uint32_t>(displayWidth),
286 static_cast<uint32_t>(displayHeight), static_cast<uint32_t>(displayDpiX / 1000))) {
287 ALOGE("%s host failed to set display %" PRIu32, __func__, displayId);
288 hostCon->unlock();
289 return HWC3::Error::NoResources;
290 }
291 hostCon->unlock();
292 } else {
293 // Secondary display:
294 static constexpr const uint32_t kHostDisplayIdStart = 6;
295
296 uint32_t expectedHostDisplayId = kHostDisplayIdStart + displayId - 1;
297 uint32_t actualHostDisplayId = 0;
298
299 hostCon->lock();
300 rcEnc->rcDestroyDisplay(rcEnc, expectedHostDisplayId);
301 rcEnc->rcCreateDisplay(rcEnc, &actualHostDisplayId);
302 rcEnc->rcSetDisplayPose(rcEnc, actualHostDisplayId, -1, -1,
303 static_cast<uint32_t>(displayWidth),
304 static_cast<uint32_t>(displayHeight));
305 hostCon->unlock();
306
307 if (actualHostDisplayId != expectedHostDisplayId) {
308 ALOGE(
309 "Something wrong with host displayId allocation, expected %d "
310 "but received %d",
311 expectedHostDisplayId, actualHostDisplayId);
312 }
313
314 hostDisplayId = actualHostDisplayId;
315 }
316
317 error = createHostComposerDisplayInfo(display, hostDisplayId);
318 if (error != HWC3::Error::None) {
319 ALOGE("%s failed to initialize host info for display:%" PRIu32, __FUNCTION__, displayId);
320 return error;
321 }
322
323 std::optional<std::vector<uint8_t>> edid;
324 if (mDrmClient) {
325 edid = mDrmClient->getEdid(displayId);
326 if (edid) {
327 display->setEdid(*edid);
328 }
329 }
330
331 return HWC3::Error::None;
332 }
333
onDisplayDestroy(Display * display)334 HWC3::Error HostFrameComposer::onDisplayDestroy(Display* display) {
335 int64_t displayId = display->getId();
336
337 auto it = mDisplayInfos.find(displayId);
338 if (it == mDisplayInfos.end()) {
339 ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__, displayId);
340 return HWC3::Error::BadDisplay;
341 }
342
343 HostComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
344
345 if (displayId != 0) {
346 DEFINE_AND_VALIDATE_HOST_CONNECTION
347 hostCon->lock();
348 rcEnc->rcDestroyDisplay(rcEnc, displayInfo.hostDisplayId);
349 hostCon->unlock();
350 }
351
352 mDisplayInfos.erase(it);
353
354 return HWC3::Error::None;
355 }
356
onDisplayClientTargetSet(Display * display)357 HWC3::Error HostFrameComposer::onDisplayClientTargetSet(Display* display) {
358 int64_t displayId = display->getId();
359
360 auto it = mDisplayInfos.find(displayId);
361 if (it == mDisplayInfos.end()) {
362 ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__, displayId);
363 return HWC3::Error::BadDisplay;
364 }
365
366 HostComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
367
368 if (mIsMinigbm) {
369 FencedBuffer& clientTargetFencedBuffer = display->getClientTarget();
370
371 auto [drmBufferCreateError, drmBuffer] =
372 mDrmClient->create(clientTargetFencedBuffer.getBuffer());
373 if (drmBufferCreateError != HWC3::Error::None) {
374 ALOGE("%s: display:%" PRIu64 " failed to create client target drm buffer", __FUNCTION__,
375 displayId);
376 return HWC3::Error::NoResources;
377 }
378 displayInfo.clientTargetDrmBuffer = std::move(drmBuffer);
379 }
380
381 return HWC3::Error::None;
382 }
383
validateDisplay(Display * display,DisplayChanges * outChanges)384 HWC3::Error HostFrameComposer::validateDisplay(Display* display, DisplayChanges* outChanges) {
385 const auto& displayId = display->getId();
386
387 DEFINE_AND_VALIDATE_HOST_CONNECTION
388 hostCon->lock();
389 bool hostCompositionV1 = rcEnc->hasHostCompositionV1();
390 bool hostCompositionV2 = rcEnc->hasHostCompositionV2();
391 hostCon->unlock();
392
393 const std::vector<Layer*> layers = display->getOrderedLayers();
394 for (const auto& layer : layers) {
395 switch (layer->getCompositionType()) {
396 case Composition::INVALID:
397 // Log error for unused layers, layer leak?
398 ALOGE("%s layer:%" PRIu64 " CompositionType not set", __FUNCTION__, layer->getId());
399 break;
400 case Composition::DISPLAY_DECORATION:
401 return HWC3::Error::Unsupported;
402 default:
403 break;
404 }
405 }
406
407 // If one layer requires a fall back to the client composition type, all
408 // layers will fall back to the client composition type.
409 bool fallBackToClient = (!hostCompositionV1 && !hostCompositionV2);
410 std::unordered_map<Layer*, Composition> changes;
411
412 if (!fallBackToClient) {
413 for (const auto& layer : layers) {
414 const auto& layerCompositionType = layer->getCompositionType();
415 const auto layerCompositionTypeString = toString(layerCompositionType);
416
417 std::optional<Composition> layerFallBackTo = std::nullopt;
418 switch (layerCompositionType) {
419 case Composition::CLIENT:
420 case Composition::SIDEBAND:
421 ALOGV("%s: layer %" PRIu32 " CompositionType %s, fallback to client",
422 __FUNCTION__, static_cast<uint32_t>(layer->getId()),
423 layerCompositionTypeString.c_str());
424 layerFallBackTo = Composition::CLIENT;
425 break;
426 case Composition::CURSOR:
427 ALOGV("%s: layer %" PRIu32 " CompositionType %s, fallback to device",
428 __FUNCTION__, static_cast<uint32_t>(layer->getId()),
429 layerCompositionTypeString.c_str());
430 layerFallBackTo = Composition::DEVICE;
431 break;
432 case Composition::INVALID:
433 case Composition::DEVICE:
434 case Composition::SOLID_COLOR:
435 layerFallBackTo = std::nullopt;
436 break;
437 default:
438 ALOGE("%s: layer %" PRIu32 " has an unknown composition type: %s", __FUNCTION__,
439 static_cast<uint32_t>(layer->getId()),
440 layerCompositionTypeString.c_str());
441 }
442 if (layer->hasLuts()) {
443 layerFallBackTo = Composition::CLIENT;
444 }
445 if (layerFallBackTo == Composition::CLIENT) {
446 fallBackToClient = true;
447 }
448 if (layerFallBackTo.has_value()) {
449 changes.emplace(layer, layerFallBackTo.value());
450 }
451 }
452 }
453
454 if (fallBackToClient) {
455 changes.clear();
456 for (auto& layer : layers) {
457 if (layer->getCompositionType() == Composition::INVALID) {
458 continue;
459 }
460 if (layer->getCompositionType() != Composition::CLIENT) {
461 changes.emplace(layer, Composition::CLIENT);
462 }
463 }
464 }
465
466 outChanges->clearLayerCompositionChanges();
467 for (auto& [layer, newCompositionType] : changes) {
468 layer->logCompositionFallbackIfChanged(newCompositionType);
469 outChanges->addLayerCompositionChange(displayId, layer->getId(), newCompositionType);
470 }
471
472 return HWC3::Error::None;
473 }
474
presentDisplay(Display * display,::android::base::unique_fd * outDisplayFence,std::unordered_map<int64_t,::android::base::unique_fd> * outLayerFences)475 HWC3::Error HostFrameComposer::presentDisplay(
476 Display* display, ::android::base::unique_fd* outDisplayFence,
477 std::unordered_map<int64_t, ::android::base::unique_fd>* outLayerFences) {
478 const uint32_t displayId = static_cast<uint32_t>(display->getId());
479 auto displayInfoIt = mDisplayInfos.find(displayId);
480 if (displayInfoIt == mDisplayInfos.end()) {
481 ALOGE("%s: failed to find display buffers for display:%" PRIu32, __FUNCTION__, displayId);
482 return HWC3::Error::BadDisplay;
483 }
484
485 HostComposerDisplayInfo& displayInfo = displayInfoIt->second;
486
487 HostConnection* hostCon;
488 ExtendedRCEncoderContext* rcEnc;
489 HWC3::Error error = getAndValidateHostConnection(&hostCon, &rcEnc);
490 if (error != HWC3::Error::None) {
491 return error;
492 }
493 *outDisplayFence = ::android::base::unique_fd();
494 hostCon->lock();
495 bool hostCompositionV1 = rcEnc->hasHostCompositionV1();
496 bool hostCompositionV2 = rcEnc->hasHostCompositionV2();
497 hostCon->unlock();
498
499 // Ff we supports v2, then discard v1
500 if (hostCompositionV2) {
501 hostCompositionV1 = false;
502 }
503
504 auto compositionResult = displayInfo.swapchain->getNextImage();
505 compositionResult->wait();
506
507 const std::vector<Layer*> layers = display->getOrderedLayers();
508 if (hostCompositionV2 || hostCompositionV1) {
509 uint32_t numLayer = 0;
510 for (auto layer : layers) {
511 if (layer->getCompositionType() == Composition::DEVICE ||
512 layer->getCompositionType() == Composition::SOLID_COLOR) {
513 numLayer++;
514 }
515 }
516
517 DEBUG_LOG("%s: presenting display:%" PRIu32 " with %d layers", __FUNCTION__, displayId,
518 static_cast<int>(layers.size()));
519
520 if (numLayer == 0) {
521 ALOGV("%s display has no layers to compose, flushing client target buffer.",
522 __FUNCTION__);
523
524 FencedBuffer& displayClientTarget = display->getClientTarget();
525 if (displayClientTarget.getBuffer() != nullptr) {
526 ::android::base::unique_fd fence = displayClientTarget.getFence();
527 if (mIsMinigbm) {
528 auto [_, flushCompleteFence] = mDrmClient->flushToDisplay(
529 displayId, displayInfo.clientTargetDrmBuffer, fence);
530
531 *outDisplayFence = std::move(flushCompleteFence);
532 } else {
533 post(hostCon, rcEnc, displayInfo.hostDisplayId,
534 displayClientTarget.getBuffer());
535 *outDisplayFence = std::move(fence);
536 }
537 }
538 return HWC3::Error::None;
539 }
540
541 std::unique_ptr<ComposeMsg> composeMsg;
542 std::unique_ptr<ComposeMsg_v2> composeMsgV2;
543
544 if (hostCompositionV1) {
545 composeMsg.reset(new ComposeMsg(numLayer));
546 } else {
547 composeMsgV2.reset(new ComposeMsg_v2(numLayer));
548 }
549
550 // Handle the composition
551 ComposeDevice* p;
552 ComposeDevice_v2* p2;
553 ComposeLayer* l;
554
555 if (hostCompositionV1) {
556 p = composeMsg->get();
557 l = p->layer;
558 } else {
559 p2 = composeMsgV2->get();
560 l = p2->layer;
561 }
562
563 std::vector<int64_t> releaseLayerIds;
564 for (auto layer : layers) {
565 const auto& layerCompositionType = layer->getCompositionType();
566 const auto layerCompositionTypeString = toString(layerCompositionType);
567
568 // TODO: use local var composisitonType to store getCompositionType()
569 if (layerCompositionType != Composition::DEVICE &&
570 layerCompositionType != Composition::SOLID_COLOR) {
571 ALOGE("%s: Unsupported composition type %s layer %u", __FUNCTION__,
572 layerCompositionTypeString.c_str(), (uint32_t)layer->getId());
573 continue;
574 }
575 // send layer composition command to host
576 if (layerCompositionType == Composition::DEVICE) {
577 releaseLayerIds.emplace_back(layer->getId());
578
579 ::android::base::unique_fd fence = layer->getBuffer().getFence();
580 if (fence.ok()) {
581 int err = sync_wait(fence.get(), 3000);
582 if (err < 0 && errno == ETIME) {
583 ALOGE("%s waited on fence %d for 3000 ms", __FUNCTION__, fence.get());
584 }
585
586 #if GOLDFISH_OPENGL_SYNC_DEBUG
587 mSyncHelper->debugPrint(fence.get());
588 #endif
589 } else {
590 ALOGV("%s: acquire fence not set for layer %u", __FUNCTION__,
591 (uint32_t)layer->getId());
592 }
593 const native_handle_t* cb = layer->getBuffer().getBuffer();
594 if (cb != nullptr) {
595 l->cbHandle = hostCon->grallocHelper()->getHostHandle(cb);
596 } else {
597 ALOGE("%s null buffer for layer %d", __FUNCTION__, (uint32_t)layer->getId());
598 }
599 } else {
600 // solidcolor has no buffer
601 l->cbHandle = 0;
602 }
603 l->composeMode = (hwc2_composition_t)layerCompositionType;
604 l->displayFrame = AsHwcRect(layer->getDisplayFrame());
605 l->crop = AsHwcFrect(layer->getSourceCrop());
606 l->blendMode = static_cast<int32_t>(layer->getBlendMode());
607 float alpha = layer->getPlaneAlpha();
608 float brightness = layer->getBrightness();
609 // Apply brightness by modulating the layer's alpha.
610 //
611 // Due to limitations in the current implementation, per-layer brightness control
612 // is not supported. To simulate the desired visual effect, brightness is approximated
613 // by adjusting the alpha value of the layer.
614 //
615 // This approach, while not ideal, is sufficient enough for a virtual device (TV
616 // Cuttlefish) because virtual displays based on Virtio GPU do not have per-layer
617 // brightness control.
618
619 float mixFactor = 0.5f;
620 l->alpha = (alpha * (1.0f - mixFactor)) + (brightness * mixFactor);
621 l->color = AsHwcColor(layer->getColor());
622 l->transform = AsHwcTransform(layer->getTransform());
623 ALOGV(
624 " cb %d blendmode %d alpha %f %d %d %d %d z %d"
625 " composeMode %d, transform %d",
626 l->cbHandle, l->blendMode, l->alpha, l->displayFrame.left, l->displayFrame.top,
627 l->displayFrame.right, l->displayFrame.bottom, layer->getZOrder(), l->composeMode,
628 l->transform);
629 l++;
630 }
631
632 if (hostCompositionV1) {
633 p->version = 1;
634 p->targetHandle =
635 hostCon->grallocHelper()->getHostHandle(compositionResult->getBuffer());
636 p->numLayers = numLayer;
637 } else {
638 p2->version = 2;
639 p2->displayId = displayInfo.hostDisplayId;
640 p2->targetHandle =
641 hostCon->grallocHelper()->getHostHandle(compositionResult->getBuffer());
642 p2->numLayers = numLayer;
643 }
644
645 void* buffer;
646 uint32_t bufferSize;
647 if (hostCompositionV1) {
648 buffer = (void*)p;
649 bufferSize = sizeof(ComposeDevice) + numLayer * sizeof(ComposeLayer);
650 } else {
651 bufferSize = sizeof(ComposeDevice_v2) + numLayer * sizeof(ComposeLayer);
652 buffer = (void*)p2;
653 }
654
655 ::android::base::unique_fd retire_fd;
656 hostCon->lock();
657 if (rcEnc->hasAsyncFrameCommands()) {
658 if (mIsMinigbm) {
659 rcEnc->rcComposeAsyncWithoutPost(rcEnc, bufferSize, buffer);
660 } else {
661 rcEnc->rcComposeAsync(rcEnc, bufferSize, buffer);
662 }
663 } else {
664 if (mIsMinigbm) {
665 rcEnc->rcComposeWithoutPost(rcEnc, bufferSize, buffer);
666 } else {
667 rcEnc->rcCompose(rcEnc, bufferSize, buffer);
668 }
669 }
670 hostCon->unlock();
671
672 // Send a retire fence and use it as the release fence for all layers,
673 // since media expects it
674 EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID};
675
676 uint64_t sync_handle, thread_handle;
677
678 // We don't use rc command to sync if we are using virtio-gpu, which is
679 // proxied by minigbm.
680 bool useRcCommandToSync = !mIsMinigbm;
681
682 if (useRcCommandToSync) {
683 hostCon->lock();
684 rcEnc->rcCreateSyncKHR(rcEnc, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs,
685 2 * sizeof(EGLint), true /* destroy when signaled */,
686 &sync_handle, &thread_handle);
687 hostCon->unlock();
688 }
689
690 if (mIsMinigbm) {
691 auto [_, fence] =
692 mDrmClient->flushToDisplay(displayId, compositionResult->getDrmBuffer(), -1);
693 retire_fd = std::move(fence);
694 } else {
695 int fd;
696 goldfish_sync_queue_work(mSyncDeviceFd, sync_handle, thread_handle, &fd);
697 retire_fd = ::android::base::unique_fd(fd);
698 }
699
700 for (int64_t layerId : releaseLayerIds) {
701 (*outLayerFences)[layerId] = ::android::base::unique_fd(dup(retire_fd.get()));
702 }
703 *outDisplayFence = ::android::base::unique_fd(dup(retire_fd.get()));
704
705 if (useRcCommandToSync) {
706 hostCon->lock();
707 if (rcEnc->hasAsyncFrameCommands()) {
708 rcEnc->rcDestroySyncKHRAsync(rcEnc, sync_handle);
709 } else {
710 rcEnc->rcDestroySyncKHR(rcEnc, sync_handle);
711 }
712 hostCon->unlock();
713 }
714 } else {
715 // we set all layers Composition::CLIENT, so do nothing.
716 FencedBuffer& displayClientTarget = display->getClientTarget();
717 ::android::base::unique_fd displayClientTargetFence = displayClientTarget.getFence();
718 if (mIsMinigbm) {
719 auto [_, flushFence] = mDrmClient->flushToDisplay(
720 displayId, compositionResult->getDrmBuffer(), displayClientTargetFence);
721 *outDisplayFence = std::move(flushFence);
722 } else {
723 post(hostCon, rcEnc, displayInfo.hostDisplayId, displayClientTarget.getBuffer());
724 *outDisplayFence = std::move(displayClientTargetFence);
725 }
726 ALOGV("%s fallback to post, returns outRetireFence %d", __FUNCTION__,
727 outDisplayFence->get());
728 }
729 compositionResult->markAsInUse(outDisplayFence->ok()
730 ? ::android::base::unique_fd(dup(*outDisplayFence))
731 : ::android::base::unique_fd());
732 return HWC3::Error::None;
733 }
734
post(HostConnection * hostCon,ExtendedRCEncoderContext * rcEnc,uint32_t hostDisplayId,buffer_handle_t h)735 void HostFrameComposer::post(HostConnection* hostCon, ExtendedRCEncoderContext* rcEnc,
736 uint32_t hostDisplayId, buffer_handle_t h) {
737 assert(cb && "native_handle_t::from(h) failed");
738
739 hostCon->lock();
740 rcEnc->rcSetDisplayColorBuffer(rcEnc, hostDisplayId,
741 hostCon->grallocHelper()->getHostHandle(h));
742 rcEnc->rcFBPost(rcEnc, hostCon->grallocHelper()->getHostHandle(h));
743 hostCon->flush();
744 hostCon->unlock();
745 }
746
onActiveConfigChange(Display * display)747 HWC3::Error HostFrameComposer::onActiveConfigChange(Display* display) {
748 const uint32_t displayId = static_cast<uint32_t>(display->getId());
749 DEBUG_LOG("%s: display:%" PRIu32, __FUNCTION__, displayId);
750 HWC3::Error error = createHostComposerDisplayInfo(display, displayId);
751 if (error != HWC3::Error::None) {
752 ALOGE("%s failed to update host info for display:%" PRIu32, __FUNCTION__, displayId);
753 return error;
754 }
755 return HWC3::Error::None;
756 }
757
758 } // namespace aidl::android::hardware::graphics::composer3::impl
759