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