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