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 "GuestFrameComposer.h"
18 
19 #include <android-base/parseint.h>
20 #include <android-base/properties.h>
21 #include <android-base/strings.h>
22 #include <android/hardware/graphics/common/1.0/types.h>
23 #include <drm_fourcc.h>
24 #include <libyuv.h>
25 #include <sync/sync.h>
26 #include <ui/GraphicBuffer.h>
27 #include <ui/GraphicBufferAllocator.h>
28 #include <ui/GraphicBufferMapper.h>
29 
30 #include "Display.h"
31 #include "DisplayFinder.h"
32 #include "Drm.h"
33 #include "Layer.h"
34 
35 namespace aidl::android::hardware::graphics::composer3::impl {
36 namespace {
37 
38 using ::android::hardware::graphics::common::V1_0::ColorTransform;
39 
AlignToPower2(uint32_t val,uint8_t align_log)40 uint32_t AlignToPower2(uint32_t val, uint8_t align_log) {
41     uint32_t align = 1 << align_log;
42     return ((val + (align - 1)) / align) * align;
43 }
44 
LayerNeedsScaling(const Layer & layer)45 bool LayerNeedsScaling(const Layer& layer) {
46     common::Rect crop = layer.getSourceCropInt();
47     common::Rect frame = layer.getDisplayFrame();
48 
49     int fromW = crop.right - crop.left;
50     int fromH = crop.bottom - crop.top;
51     int toW = frame.right - frame.left;
52     int toH = frame.bottom - frame.top;
53 
54     bool not_rot_scale = fromW != toW || fromH != toH;
55     bool rot_scale = fromW != toH || fromH != toW;
56 
57     bool needs_rot = static_cast<int32_t>(layer.getTransform()) &
58                      static_cast<int32_t>(common::Transform::ROT_90);
59 
60     return needs_rot ? rot_scale : not_rot_scale;
61 }
62 
LayerNeedsBlending(const Layer & layer)63 bool LayerNeedsBlending(const Layer& layer) {
64     return layer.getBlendMode() != common::BlendMode::NONE;
65 }
66 
LayerNeedsAttenuation(const Layer & layer)67 bool LayerNeedsAttenuation(const Layer& layer) {
68     return layer.getBlendMode() == common::BlendMode::COVERAGE;
69 }
70 
71 struct BufferSpec;
72 typedef int (*ConverterFunction)(const BufferSpec& src, const BufferSpec& dst, bool v_flip);
73 int DoCopy(const BufferSpec& src, const BufferSpec& dst, bool vFlip);
74 int ConvertFromRGB565(const BufferSpec& src, const BufferSpec& dst, bool vFlip);
75 int ConvertFromYV12(const BufferSpec& src, const BufferSpec& dst, bool vFlip);
76 
GetConverterForDrmFormat(uint32_t drmFormat)77 ConverterFunction GetConverterForDrmFormat(uint32_t drmFormat) {
78     switch (drmFormat) {
79         case DRM_FORMAT_ABGR8888:
80         case DRM_FORMAT_XBGR8888:
81             return &DoCopy;
82         case DRM_FORMAT_RGB565:
83             return &ConvertFromRGB565;
84         case DRM_FORMAT_YVU420:
85             return &ConvertFromYV12;
86     }
87     DEBUG_LOG("Unsupported drm format: %d(%s), returning null converter", drmFormat,
88               GetDrmFormatString(drmFormat));
89     return nullptr;
90 }
91 
IsDrmFormatSupported(uint32_t drmFormat)92 bool IsDrmFormatSupported(uint32_t drmFormat) {
93     return GetConverterForDrmFormat(drmFormat) != nullptr;
94 }
95 
96 // Libyuv's convert functions only allow the combination of any rotation
97 // (multiple of 90 degrees) and a vertical flip, but not horizontal flips.
98 // Surfaceflinger's transformations are expressed in terms of a vertical flip,
99 // a horizontal flip and/or a single 90 degrees clockwise rotation (see
100 // NATIVE_WINDOW_TRANSFORM_HINT documentation on system/window.h for more
101 // insight). The following code allows to turn a horizontal flip into a 180
102 // degrees rotation and a vertical flip.
GetRotationFromTransform(common::Transform transform)103 libyuv::RotationMode GetRotationFromTransform(common::Transform transform) {
104     uint32_t rotation = 0;
105     rotation += (static_cast<int32_t>(transform) & static_cast<int32_t>(common::Transform::ROT_90))
106                     ? 1
107                     : 0;  // 1 * ROT90 bit
108     rotation += (static_cast<int32_t>(transform) & static_cast<int32_t>(common::Transform::FLIP_H))
109                     ? 2
110                     : 0;  // 2 * VFLIP bit
111     return static_cast<libyuv::RotationMode>(90 * rotation);
112 }
113 
GetVFlipFromTransform(common::Transform transform)114 bool GetVFlipFromTransform(common::Transform transform) {
115     // vertical flip xor horizontal flip
116     bool hasVFlip =
117         static_cast<int32_t>(transform) & static_cast<int32_t>(common::Transform::FLIP_V);
118     bool hasHFlip =
119         static_cast<int32_t>(transform) & static_cast<int32_t>(common::Transform::FLIP_H);
120     return hasVFlip ^ hasHFlip;
121 }
122 
123 struct BufferSpec {
124     uint8_t* buffer;
125     std::optional<android_ycbcr> buffer_ycbcr;
126     uint32_t width;
127     uint32_t height;
128     uint32_t cropX;
129     uint32_t cropY;
130     uint32_t cropWidth;
131     uint32_t cropHeight;
132     uint32_t drmFormat;
133     uint32_t strideBytes;
134     uint32_t sampleBytes;
135 
136     BufferSpec() = default;
137 
BufferSpecaidl::android::hardware::graphics::composer3::impl::__anon502f7dff0111::BufferSpec138     BufferSpec(uint8_t* buffer, std::optional<android_ycbcr> buffer_ycbcr, uint32_t width,
139                uint32_t height, uint32_t cropX, uint32_t cropY, uint32_t cropWidth,
140                uint32_t cropHeight, uint32_t drmFormat, uint32_t strideBytes, uint32_t sampleBytes)
141         : buffer(buffer),
142           buffer_ycbcr(buffer_ycbcr),
143           width(width),
144           height(height),
145           cropX(cropX),
146           cropY(cropY),
147           cropWidth(cropWidth),
148           cropHeight(cropHeight),
149           drmFormat(drmFormat),
150           strideBytes(strideBytes),
151           sampleBytes(sampleBytes) {}
152 
BufferSpecaidl::android::hardware::graphics::composer3::impl::__anon502f7dff0111::BufferSpec153     BufferSpec(uint8_t* buffer, uint32_t width, uint32_t height, uint32_t strideBytes)
154         : BufferSpec(buffer,
155                      /*buffer_ycbcr=*/std::nullopt, width, height,
156                      /*cropX=*/0,
157                      /*cropY=*/0,
158                      /*cropWidth=*/width,
159                      /*cropHeight=*/height,
160                      /*drmFormat=*/DRM_FORMAT_ABGR8888, strideBytes,
161                      /*sampleBytes=*/4) {}
162 };
163 
DoFill(const BufferSpec & dst,const Color & color)164 int DoFill(const BufferSpec& dst, const Color& color) {
165     ATRACE_CALL();
166 
167     const uint8_t r = static_cast<uint8_t>(color.r * 255.0f);
168     const uint8_t g = static_cast<uint8_t>(color.g * 255.0f);
169     const uint8_t b = static_cast<uint8_t>(color.b * 255.0f);
170     const uint8_t a = static_cast<uint8_t>(color.a * 255.0f);
171 
172     const uint32_t rgba = static_cast<uint32_t>(r) | static_cast<uint32_t>(g) << 8 |
173                           static_cast<uint32_t>(b) << 16 | static_cast<uint32_t>(a) << 24;
174 
175     // Point to the upper left corner of the crop rectangle.
176     uint8_t* dstBuffer = dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
177 
178     libyuv::SetPlane(dstBuffer, static_cast<int>(dst.strideBytes), static_cast<int>(dst.cropWidth),
179                      static_cast<int>(dst.cropHeight), rgba);
180     return 0;
181 }
182 
ConvertFromRGB565(const BufferSpec & src,const BufferSpec & dst,bool vFlip)183 int ConvertFromRGB565(const BufferSpec& src, const BufferSpec& dst, bool vFlip) {
184     ATRACE_CALL();
185 
186     // Point to the upper left corner of the crop rectangle
187     uint8_t* srcBuffer = src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
188     const int srcStrideBytes = static_cast<int>(src.strideBytes);
189     uint8_t* dstBuffer = dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
190     const int dstStrideBytes = static_cast<int>(dst.strideBytes);
191 
192     int width = static_cast<int>(src.cropWidth);
193     int height = static_cast<int>(src.cropHeight);
194     if (vFlip) {
195         height = -height;
196     }
197 
198     return libyuv::RGB565ToARGB(srcBuffer, srcStrideBytes,  //
199                                 dstBuffer, dstStrideBytes,  //
200                                 width, height);
201 }
202 
ConvertFromYV12(const BufferSpec & src,const BufferSpec & dst,bool vFlip)203 int ConvertFromYV12(const BufferSpec& src, const BufferSpec& dst, bool vFlip) {
204     ATRACE_CALL();
205 
206     // The following calculation of plane offsets and alignments are based on
207     // swiftshader's Sampler::setTextureLevel() implementation
208     // (Renderer/Sampler.cpp:225)
209 
210     auto& srcBufferYCbCrOpt = src.buffer_ycbcr;
211     if (!srcBufferYCbCrOpt) {
212         ALOGE("%s called on non ycbcr buffer", __FUNCTION__);
213         return -1;
214     }
215     auto& srcBufferYCbCr = *srcBufferYCbCrOpt;
216 
217     // The libyuv::I420ToARGB() function is for tri-planar.
218     if (srcBufferYCbCr.chroma_step != 1) {
219         ALOGE("%s called with bad chroma step", __FUNCTION__);
220         return -1;
221     }
222 
223     uint8_t* srcY = reinterpret_cast<uint8_t*>(srcBufferYCbCr.y);
224     const int strideYBytes = static_cast<int>(srcBufferYCbCr.ystride);
225     uint8_t* srcU = reinterpret_cast<uint8_t*>(srcBufferYCbCr.cb);
226     const int strideUBytes = static_cast<int>(srcBufferYCbCr.cstride);
227     uint8_t* srcV = reinterpret_cast<uint8_t*>(srcBufferYCbCr.cr);
228     const int strideVBytes = static_cast<int>(srcBufferYCbCr.cstride);
229 
230     // Adjust for crop
231     srcY += src.cropY * srcBufferYCbCr.ystride + src.cropX;
232     srcV += (src.cropY / 2) * srcBufferYCbCr.cstride + (src.cropX / 2);
233     srcU += (src.cropY / 2) * srcBufferYCbCr.cstride + (src.cropX / 2);
234     uint8_t* dstBuffer = dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
235     const int dstStrideBytes = static_cast<int>(dst.strideBytes);
236 
237     int width = static_cast<int>(dst.cropWidth);
238     int height = static_cast<int>(dst.cropHeight);
239 
240     if (vFlip) {
241         height = -height;
242     }
243 
244     // YV12 is the same as I420, with the U and V planes swapped
245     return libyuv::I420ToARGB(srcY, strideYBytes,  //
246                               srcV, strideVBytes,  //
247                               srcU, strideUBytes,  //
248                               dstBuffer, dstStrideBytes, width, height);
249 }
250 
DoConversion(const BufferSpec & src,const BufferSpec & dst,bool v_flip)251 int DoConversion(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
252     ConverterFunction func = GetConverterForDrmFormat(src.drmFormat);
253     if (!func) {
254         // GetConverterForDrmFormat should've logged the issue for us.
255         return -1;
256     }
257     return func(src, dst, v_flip);
258 }
259 
DoCopy(const BufferSpec & src,const BufferSpec & dst,bool v_flip)260 int DoCopy(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
261     ATRACE_CALL();
262 
263     // Point to the upper left corner of the crop rectangle
264     uint8_t* srcBuffer = src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
265     const int srcStrideBytes = static_cast<int>(src.strideBytes);
266     uint8_t* dstBuffer = dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
267     const int dstStrideBytes = static_cast<int>(dst.strideBytes);
268     int width = static_cast<int>(src.cropWidth);
269     int height = static_cast<int>(src.cropHeight);
270 
271     if (v_flip) {
272         height = -height;
273     }
274 
275     // HAL formats are named based on the order of the pixel components on the
276     // byte stream, while libyuv formats are named based on the order of those
277     // pixel components in an integer written from left to right. So
278     // libyuv::FOURCC_ARGB is equivalent to HAL_PIXEL_FORMAT_BGRA_8888.
279     auto ret = libyuv::ARGBCopy(srcBuffer, srcStrideBytes,  //
280                                 dstBuffer, dstStrideBytes,  //
281                                 width, height);
282     return ret;
283 }
284 
DoRotation(const BufferSpec & src,const BufferSpec & dst,libyuv::RotationMode rotation,bool v_flip)285 int DoRotation(const BufferSpec& src, const BufferSpec& dst, libyuv::RotationMode rotation,
286                bool v_flip) {
287     ATRACE_CALL();
288 
289     // Point to the upper left corner of the crop rectangles
290     uint8_t* srcBuffer = src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
291     const int srcStrideBytes = static_cast<int>(src.strideBytes);
292     uint8_t* dstBuffer = dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
293     const int dstStrideBytes = static_cast<int>(dst.strideBytes);
294     int width = static_cast<int>(src.cropWidth);
295     int height = static_cast<int>(src.cropHeight);
296 
297     if (v_flip) {
298         height = -height;
299     }
300 
301     return libyuv::ARGBRotate(srcBuffer, srcStrideBytes,  //
302                               dstBuffer, dstStrideBytes,  //
303                               width, height, rotation);
304 }
305 
DoScaling(const BufferSpec & src,const BufferSpec & dst,bool v_flip)306 int DoScaling(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
307     ATRACE_CALL();
308 
309     // Point to the upper left corner of the crop rectangles
310     uint8_t* srcBuffer = src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
311     uint8_t* dstBuffer = dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
312     const int srcStrideBytes = static_cast<int>(src.strideBytes);
313     const int dstStrideBytes = static_cast<int>(dst.strideBytes);
314     const int srcWidth = static_cast<int>(src.cropWidth);
315     int srcHeight = static_cast<int>(src.cropHeight);
316     const int dstWidth = static_cast<int>(dst.cropWidth);
317     const int dstHeight = static_cast<int>(dst.cropHeight);
318 
319     if (v_flip) {
320         srcHeight = -srcHeight;
321     }
322 
323     return libyuv::ARGBScale(srcBuffer, srcStrideBytes, srcWidth, srcHeight, dstBuffer,
324                              dstStrideBytes, dstWidth, dstHeight, libyuv::kFilterBilinear);
325 }
326 
DoAttenuation(const BufferSpec & src,const BufferSpec & dst,bool v_flip)327 int DoAttenuation(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
328     ATRACE_CALL();
329 
330     // Point to the upper left corner of the crop rectangles
331     uint8_t* srcBuffer = src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
332     uint8_t* dstBuffer = dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
333     const int srcStrideBytes = static_cast<int>(src.strideBytes);
334     const int dstStrideBytes = static_cast<int>(dst.strideBytes);
335     const int width = static_cast<int>(dst.cropWidth);
336     int height = static_cast<int>(dst.cropHeight);
337     if (v_flip) {
338         height = -height;
339     }
340 
341     return libyuv::ARGBAttenuate(srcBuffer, srcStrideBytes,  //
342                                  dstBuffer, dstStrideBytes,  //
343                                  width, height);
344 }
345 
DoBlending(const BufferSpec & src,const BufferSpec & dst,bool v_flip)346 int DoBlending(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
347     ATRACE_CALL();
348 
349     // Point to the upper left corner of the crop rectangles
350     uint8_t* srcBuffer = src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
351     uint8_t* dstBuffer = dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
352     const int srcStrideBytes = static_cast<int>(src.strideBytes);
353     const int dstStrideBytes = static_cast<int>(dst.strideBytes);
354     const int width = static_cast<int>(dst.cropWidth);
355     int height = static_cast<int>(dst.cropHeight);
356     if (v_flip) {
357         height = -height;
358     }
359 
360     // libyuv's ARGB format is hwcomposer's BGRA format, since blending only cares
361     // for the position of alpha in the pixel and not the position of the colors
362     // this function is perfectly usable.
363     return libyuv::ARGBBlend(srcBuffer, srcStrideBytes,  //
364                              dstBuffer, dstStrideBytes,  //
365                              dstBuffer, dstStrideBytes,  //
366                              width, height);
367 }
368 
GetBufferSpec(GrallocBuffer & buffer,GrallocBufferView & bufferView,const common::Rect & bufferCrop)369 std::optional<BufferSpec> GetBufferSpec(GrallocBuffer& buffer, GrallocBufferView& bufferView,
370                                         const common::Rect& bufferCrop) {
371     auto bufferFormatOpt = buffer.GetDrmFormat();
372     if (!bufferFormatOpt) {
373         ALOGE("Failed to get gralloc buffer format.");
374         return std::nullopt;
375     }
376     uint32_t bufferFormat = *bufferFormatOpt;
377 
378     auto bufferWidthOpt = buffer.GetWidth();
379     if (!bufferWidthOpt) {
380         ALOGE("Failed to get gralloc buffer width.");
381         return std::nullopt;
382     }
383     uint32_t bufferWidth = *bufferWidthOpt;
384 
385     auto bufferHeightOpt = buffer.GetHeight();
386     if (!bufferHeightOpt) {
387         ALOGE("Failed to get gralloc buffer height.");
388         return std::nullopt;
389     }
390     uint32_t bufferHeight = *bufferHeightOpt;
391 
392     uint8_t* bufferData = nullptr;
393     uint32_t bufferStrideBytes = 0;
394     std::optional<android_ycbcr> bufferYCbCrData;
395 
396     if (bufferFormat == DRM_FORMAT_NV12 || bufferFormat == DRM_FORMAT_NV21 ||
397         bufferFormat == DRM_FORMAT_YVU420) {
398         bufferYCbCrData = bufferView.GetYCbCr();
399         if (!bufferYCbCrData) {
400             ALOGE("%s failed to get raw ycbcr from view.", __FUNCTION__);
401             return std::nullopt;
402         }
403     } else {
404         auto bufferDataOpt = bufferView.Get();
405         if (!bufferDataOpt) {
406             ALOGE("%s failed to lock gralloc buffer.", __FUNCTION__);
407             return std::nullopt;
408         }
409         bufferData = reinterpret_cast<uint8_t*>(*bufferDataOpt);
410 
411         auto bufferStrideBytesOpt = buffer.GetMonoPlanarStrideBytes();
412         if (!bufferStrideBytesOpt) {
413             ALOGE("%s failed to get plane stride.", __FUNCTION__);
414             return std::nullopt;
415         }
416         bufferStrideBytes = *bufferStrideBytesOpt;
417     }
418 
419     uint32_t bufferCropX = static_cast<uint32_t>(bufferCrop.left);
420     uint32_t bufferCropY = static_cast<uint32_t>(bufferCrop.top);
421     uint32_t bufferCropWidth = static_cast<uint32_t>(bufferCrop.right - bufferCrop.left);
422     uint32_t bufferCropHeight = static_cast<uint32_t>(bufferCrop.bottom - bufferCrop.top);
423 
424     return BufferSpec(bufferData, bufferYCbCrData, bufferWidth, bufferHeight, bufferCropX,
425                       bufferCropY, bufferCropWidth, bufferCropHeight, bufferFormat,
426                       bufferStrideBytes, GetDrmFormatBytesPerPixel(bufferFormat));
427 }
428 
429 }  // namespace
430 
init()431 HWC3::Error GuestFrameComposer::init() {
432     DEBUG_LOG("%s", __FUNCTION__);
433 
434     HWC3::Error error = mDrmClient.init();
435     if (error != HWC3::Error::None) {
436         ALOGE("%s: failed to initialize DrmClient", __FUNCTION__);
437         return error;
438     }
439 
440     return HWC3::Error::None;
441 }
442 
registerOnHotplugCallback(const HotplugCallback & cb)443 HWC3::Error GuestFrameComposer::registerOnHotplugCallback(const HotplugCallback& cb) {
444     return mDrmClient.registerOnHotplugCallback(cb);
445     return HWC3::Error::None;
446 }
447 
unregisterOnHotplugCallback()448 HWC3::Error GuestFrameComposer::unregisterOnHotplugCallback() {
449     return mDrmClient.unregisterOnHotplugCallback();
450 }
451 
onDisplayCreate(Display * display)452 HWC3::Error GuestFrameComposer::onDisplayCreate(Display* display) {
453     const uint32_t displayId = static_cast<uint32_t>(display->getId());
454     int32_t displayConfigId;
455     int32_t displayWidth;
456     int32_t displayHeight;
457 
458     HWC3::Error error = display->getActiveConfig(&displayConfigId);
459     if (error != HWC3::Error::None) {
460         ALOGE("%s: display:%" PRIu32 " has no active config", __FUNCTION__, displayId);
461         return error;
462     }
463 
464     error = display->getDisplayAttribute(displayConfigId, DisplayAttribute::WIDTH, &displayWidth);
465     if (error != HWC3::Error::None) {
466         ALOGE("%s: display:%" PRIu32 " failed to get width", __FUNCTION__, displayId);
467         return error;
468     }
469 
470     error = display->getDisplayAttribute(displayConfigId, DisplayAttribute::HEIGHT, &displayHeight);
471     if (error != HWC3::Error::None) {
472         ALOGE("%s: display:%" PRIu32 " failed to get height", __FUNCTION__, displayId);
473         return error;
474     }
475 
476     auto it = mDisplayInfos.find(displayId);
477     if (it != mDisplayInfos.end()) {
478         ALOGE("%s: display:%" PRIu32 " already created?", __FUNCTION__, displayId);
479     }
480 
481     DisplayInfo& displayInfo = mDisplayInfos[displayId];
482 
483     displayInfo.swapchain = DrmSwapchain::create(static_cast<uint32_t>(displayWidth),
484                                                  static_cast<uint32_t>(displayHeight),
485                                                  ::android::GraphicBuffer::USAGE_HW_COMPOSER |
486                                                    ::android::GraphicBuffer::USAGE_SW_READ_OFTEN |
487                                                    ::android::GraphicBuffer::USAGE_SW_WRITE_OFTEN,
488                                                  &mDrmClient);
489 
490     if (displayId == 0) {
491         auto compositionResult = displayInfo.swapchain->getNextImage();
492         auto [flushError, flushSyncFd] =
493                 mDrmClient.flushToDisplay(displayId, compositionResult->getDrmBuffer(), -1);
494         if (flushError != HWC3::Error::None) {
495             ALOGW(
496                 "%s: Initial display flush failed. HWComposer assuming that we are "
497                 "running in QEMU without a display and disabling presenting.",
498                 __FUNCTION__);
499             mPresentDisabled = true;
500         } else {
501             compositionResult->markAsInUse(std::move(flushSyncFd));
502         }
503     }
504 
505     std::optional<std::vector<uint8_t>> edid = mDrmClient.getEdid(displayId);
506     if (edid) {
507         display->setEdid(*edid);
508     }
509 
510     return HWC3::Error::None;
511 }
512 
onDisplayDestroy(Display * display)513 HWC3::Error GuestFrameComposer::onDisplayDestroy(Display* display) {
514     auto displayId = display->getId();
515 
516     auto it = mDisplayInfos.find(displayId);
517     if (it == mDisplayInfos.end()) {
518         ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__,
519             displayId);
520         return HWC3::Error::BadDisplay;
521     }
522     mDisplayInfos.erase(it);
523 
524     return HWC3::Error::None;
525 }
526 
onDisplayClientTargetSet(Display *)527 HWC3::Error GuestFrameComposer::onDisplayClientTargetSet(Display*) { return HWC3::Error::None; }
528 
onActiveConfigChange(Display *)529 HWC3::Error GuestFrameComposer::onActiveConfigChange(Display* /*display*/) {
530     return HWC3::Error::None;
531 };
532 
getDisplayConfigsFromSystemProp(std::vector<GuestFrameComposer::DisplayConfig> * configs)533 HWC3::Error GuestFrameComposer::getDisplayConfigsFromSystemProp(
534     std::vector<GuestFrameComposer::DisplayConfig>* configs) {
535     DEBUG_LOG("%s", __FUNCTION__);
536 
537     std::vector<int> propIntParts;
538     parseExternalDisplaysFromProperties(propIntParts);
539 
540     while (!propIntParts.empty()) {
541         DisplayConfig display_config = {
542             .width = propIntParts[1],
543             .height = propIntParts[2],
544             .dpiX = propIntParts[3],
545             .dpiY = propIntParts[3],
546             .refreshRateHz = 160,
547         };
548 
549         configs->push_back(display_config);
550 
551         propIntParts.erase(propIntParts.begin(), propIntParts.begin() + 5);
552     }
553 
554     return HWC3::Error::None;
555 }
556 
validateDisplay(Display * display,DisplayChanges * outChanges)557 HWC3::Error GuestFrameComposer::validateDisplay(Display* display, DisplayChanges* outChanges) {
558     const auto displayId = display->getId();
559     DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
560 
561     const std::vector<Layer*>& layers = display->getOrderedLayers();
562 
563     bool fallbackToClientComposition = false;
564     for (Layer* layer : layers) {
565         const auto layerId = layer->getId();
566         const auto layerCompositionType = layer->getCompositionType();
567         const auto layerCompositionTypeString = toString(layerCompositionType);
568 
569         if (layerCompositionType == Composition::INVALID) {
570             ALOGE("%s display:%" PRIu64 " layer:%" PRIu64 " has Invalid composition", __FUNCTION__,
571                   displayId, layerId);
572             continue;
573         }
574 
575         if (layerCompositionType == Composition::CLIENT ||
576             layerCompositionType == Composition::CURSOR ||
577             layerCompositionType == Composition::SIDEBAND) {
578             DEBUG_LOG("%s: display:%" PRIu64 " layer:%" PRIu64
579                       " has composition type %s, falling back to client composition",
580                       __FUNCTION__, displayId, layerId, layerCompositionTypeString.c_str());
581             fallbackToClientComposition = true;
582             break;
583         }
584 
585         if (layerCompositionType == Composition::DISPLAY_DECORATION) {
586             return HWC3::Error::Unsupported;
587         }
588 
589         if (!canComposeLayer(layer)) {
590             DEBUG_LOG("%s: display:%" PRIu64 " layer:%" PRIu64
591                       " composition not supported, falling back to client composition",
592                       __FUNCTION__, displayId, layerId);
593             fallbackToClientComposition = true;
594             break;
595         }
596     }
597 
598     if (fallbackToClientComposition) {
599         for (Layer* layer : layers) {
600             const auto layerId = layer->getId();
601             const auto layerCompositionType = layer->getCompositionType();
602 
603             if (layerCompositionType == Composition::INVALID) {
604                 continue;
605             }
606 
607             if (layerCompositionType != Composition::CLIENT) {
608                 DEBUG_LOG("%s display:%" PRIu64 " layer:%" PRIu64 "composition updated to Client",
609                           __FUNCTION__, displayId, layerId);
610 
611                 outChanges->addLayerCompositionChange(displayId, layerId, Composition::CLIENT);
612             }
613         }
614     }
615 
616     // We can not draw below a Client (SurfaceFlinger) composed layer. Change all
617     // layers below a Client composed layer to also be Client composed.
618     if (layers.size() > 1) {
619         for (std::size_t layerIndex = layers.size() - 1; layerIndex > 0; layerIndex--) {
620             auto layer = layers[layerIndex];
621             auto layerCompositionType = layer->getCompositionType();
622 
623             if (layerCompositionType == Composition::CLIENT) {
624                 for (std::size_t lowerLayerIndex = 0; lowerLayerIndex < layerIndex;
625                      lowerLayerIndex++) {
626                     auto lowerLayer = layers[lowerLayerIndex];
627                     auto lowerLayerId = lowerLayer->getId();
628                     auto lowerLayerCompositionType = lowerLayer->getCompositionType();
629 
630                     if (lowerLayerCompositionType != Composition::CLIENT) {
631                         DEBUG_LOG("%s: display:%" PRIu64 " changing layer:%" PRIu64
632                                   " to Client because"
633                                   "hwcomposer can not draw below the Client composed "
634                                   "layer:%" PRIu64,
635                                   __FUNCTION__, displayId, lowerLayerId, layer->getId());
636 
637                         outChanges->addLayerCompositionChange(displayId, lowerLayerId,
638                                                               Composition::CLIENT);
639                     }
640                 }
641             }
642         }
643     }
644 
645     return HWC3::Error::None;
646 }
647 
presentDisplay(Display * display,::android::base::unique_fd * outDisplayFence,std::unordered_map<int64_t,::android::base::unique_fd> *)648 HWC3::Error GuestFrameComposer::presentDisplay(
649     Display* display, ::android::base::unique_fd* outDisplayFence,
650     std::unordered_map<int64_t, ::android::base::unique_fd>* /*outLayerFences*/) {
651     const uint32_t displayId = static_cast<uint32_t>(display->getId());
652     DEBUG_LOG("%s display:%" PRIu32, __FUNCTION__, displayId);
653 
654     if (mPresentDisabled) {
655         return HWC3::Error::None;
656     }
657 
658     auto it = mDisplayInfos.find(displayId);
659     if (it == mDisplayInfos.end()) {
660         ALOGE("%s: display:%" PRIu32 " not found", __FUNCTION__, displayId);
661         return HWC3::Error::NoResources;
662     }
663 
664     DisplayInfo& displayInfo = it->second;
665 
666     auto compositionResult = displayInfo.swapchain->getNextImage();
667     compositionResult->wait();
668 
669     if (compositionResult->getBuffer() == nullptr) {
670         ALOGE("%s: display:%" PRIu32 " missing composition result buffer",
671             __FUNCTION__, displayId);
672         return HWC3::Error::NoResources;
673     }
674 
675     if (compositionResult->getDrmBuffer() == nullptr) {
676         ALOGE("%s: display:%" PRIu32 " missing composition result drm buffer",
677             __FUNCTION__, displayId);
678         return HWC3::Error::NoResources;
679     }
680 
681     std::optional<GrallocBuffer> compositionResultBufferOpt =
682         mGralloc.Import(compositionResult->getBuffer());
683     if (!compositionResultBufferOpt) {
684         ALOGE("%s: display:%" PRIu32 " failed to import buffer", __FUNCTION__, displayId);
685         return HWC3::Error::NoResources;
686     }
687 
688     std::optional<uint32_t> compositionResultBufferWidthOpt =
689         compositionResultBufferOpt->GetWidth();
690     if (!compositionResultBufferWidthOpt) {
691         ALOGE("%s: display:%" PRIu32 " failed to query buffer width", __FUNCTION__, displayId);
692         return HWC3::Error::NoResources;
693     }
694 
695     std::optional<uint32_t> compositionResultBufferHeightOpt =
696         compositionResultBufferOpt->GetHeight();
697     if (!compositionResultBufferHeightOpt) {
698         ALOGE("%s: display:%" PRIu32 " failed to query buffer height", __FUNCTION__, displayId);
699         return HWC3::Error::NoResources;
700     }
701 
702     std::optional<uint32_t> compositionResultBufferStrideOpt =
703         compositionResultBufferOpt->GetMonoPlanarStrideBytes();
704     if (!compositionResultBufferStrideOpt) {
705         ALOGE("%s: display:%" PRIu32 " failed to query buffer stride", __FUNCTION__, displayId);
706         return HWC3::Error::NoResources;
707     }
708 
709     std::optional<GrallocBufferView> compositionResultBufferViewOpt =
710         compositionResultBufferOpt->Lock();
711     if (!compositionResultBufferViewOpt) {
712         ALOGE("%s: display:%" PRIu32 " failed to get buffer view", __FUNCTION__, displayId);
713         return HWC3::Error::NoResources;
714     }
715 
716     const std::optional<void*> compositionResultBufferDataOpt =
717         compositionResultBufferViewOpt->Get();
718     if (!compositionResultBufferDataOpt) {
719         ALOGE("%s: display:%" PRIu32 " failed to get buffer data", __FUNCTION__, displayId);
720         return HWC3::Error::NoResources;
721     }
722 
723     uint32_t compositionResultBufferWidth = *compositionResultBufferWidthOpt;
724     uint32_t compositionResultBufferHeight = *compositionResultBufferHeightOpt;
725     uint32_t compositionResultBufferStride = *compositionResultBufferStrideOpt;
726     uint8_t* compositionResultBufferData =
727         reinterpret_cast<uint8_t*>(*compositionResultBufferDataOpt);
728 
729     const std::vector<Layer*>& layers = display->getOrderedLayers();
730 
731     const bool noOpComposition = layers.empty();
732     const bool allLayersClientComposed = std::all_of(
733         layers.begin(),  //
734         layers.end(),    //
735         [](const Layer* layer) { return layer->getCompositionType() == Composition::CLIENT; });
736 
737     if (noOpComposition) {
738         ALOGW("%s: display:%" PRIu32 " empty composition", __FUNCTION__, displayId);
739     } else if (allLayersClientComposed) {
740         auto clientTargetBufferOpt = mGralloc.Import(display->waitAndGetClientTargetBuffer());
741         if (!clientTargetBufferOpt) {
742             ALOGE("%s: failed to import client target buffer.", __FUNCTION__);
743             return HWC3::Error::NoResources;
744         }
745         GrallocBuffer& clientTargetBuffer = *clientTargetBufferOpt;
746 
747         auto clientTargetBufferViewOpt = clientTargetBuffer.Lock();
748         if (!clientTargetBufferViewOpt) {
749             ALOGE("%s: failed to lock client target buffer.", __FUNCTION__);
750             return HWC3::Error::NoResources;
751         }
752         GrallocBufferView& clientTargetBufferView = *clientTargetBufferViewOpt;
753 
754         auto clientTargetPlaneLayoutsOpt = clientTargetBuffer.GetPlaneLayouts();
755         if (!clientTargetPlaneLayoutsOpt) {
756             ALOGE("Failed to get client target buffer plane layouts.");
757             return HWC3::Error::NoResources;
758         }
759         auto& clientTargetPlaneLayouts = *clientTargetPlaneLayoutsOpt;
760 
761         if (clientTargetPlaneLayouts.size() != 1) {
762             ALOGE("Unexpected number of plane layouts for client target buffer.");
763             return HWC3::Error::NoResources;
764         }
765 
766         std::size_t clientTargetPlaneSize =
767             static_cast<std::size_t>(clientTargetPlaneLayouts[0].totalSizeInBytes);
768 
769         auto clientTargetDataOpt = clientTargetBufferView.Get();
770         if (!clientTargetDataOpt) {
771             ALOGE("%s failed to lock gralloc buffer.", __FUNCTION__);
772             return HWC3::Error::NoResources;
773         }
774         auto* clientTargetData = reinterpret_cast<uint8_t*>(*clientTargetDataOpt);
775 
776         std::memcpy(compositionResultBufferData, clientTargetData, clientTargetPlaneSize);
777     } else {
778         for (Layer* layer : layers) {
779             const auto layerId = layer->getId();
780             const auto layerCompositionType = layer->getCompositionType();
781             if (layerCompositionType != Composition::DEVICE &&
782                 layerCompositionType != Composition::SOLID_COLOR) {
783                 continue;
784             }
785 
786             HWC3::Error error = composeLayerInto(displayInfo.compositionIntermediateStorage,  //
787                                                  layer,                                       //
788                                                  compositionResultBufferData,                 //
789                                                  compositionResultBufferWidth,                //
790                                                  compositionResultBufferHeight,               //
791                                                  compositionResultBufferStride,               //
792                                                  4);
793             if (error != HWC3::Error::None) {
794                 ALOGE("%s: display:%" PRIu32 " failed to compose layer:%" PRIu64, __FUNCTION__,
795                       displayId, layerId);
796                 return error;
797             }
798         }
799     }
800 
801     if (display->hasColorTransform()) {
802         HWC3::Error error = applyColorTransformToRGBA(display->getColorTransform(),   //
803                                                       compositionResultBufferData,    //
804                                                       compositionResultBufferWidth,   //
805                                                       compositionResultBufferHeight,  //
806                                                       compositionResultBufferStride);
807         if (error != HWC3::Error::None) {
808             ALOGE("%s: display:%" PRIu32 " failed to apply color transform", __FUNCTION__,
809                   displayId);
810             return error;
811         }
812     }
813 
814     DEBUG_LOG("%s display:%" PRIu32 " flushing drm buffer", __FUNCTION__,
815                 displayId);
816 
817     auto [error, fence] = mDrmClient.flushToDisplay(displayId, compositionResult->getDrmBuffer(), -1);
818     if (error != HWC3::Error::None) {
819         ALOGE("%s: display:%" PRIu32 " failed to flush drm buffer" PRIu64,
820             __FUNCTION__, displayId);
821     }
822 
823     *outDisplayFence = std::move(fence);
824     compositionResult->markAsInUse(outDisplayFence->ok()
825                                         ? ::android::base::unique_fd(dup(*outDisplayFence))
826                                         : ::android::base::unique_fd());
827     return error;
828 }
829 
canComposeLayer(Layer * layer)830 bool GuestFrameComposer::canComposeLayer(Layer* layer) {
831     const auto layerCompositionType = layer->getCompositionType();
832     if (layerCompositionType == Composition::SOLID_COLOR) {
833         return true;
834     }
835 
836     if (layerCompositionType != Composition::DEVICE) {
837         return false;
838     }
839 
840     buffer_handle_t bufferHandle = layer->getBuffer().getBuffer();
841     if (bufferHandle == nullptr) {
842         ALOGW("%s received a layer with a null handle", __FUNCTION__);
843         return false;
844     }
845 
846     auto bufferOpt = mGralloc.Import(bufferHandle);
847     if (!bufferOpt) {
848         ALOGE("Failed to import layer buffer.");
849         return false;
850     }
851     GrallocBuffer& buffer = *bufferOpt;
852 
853     auto bufferFormatOpt = buffer.GetDrmFormat();
854     if (!bufferFormatOpt) {
855         ALOGE("Failed to get layer buffer format.");
856         return false;
857     }
858     uint32_t bufferFormat = *bufferFormatOpt;
859 
860     if (!IsDrmFormatSupported(bufferFormat)) {
861         return false;
862     }
863 
864     return true;
865 }
866 
composeLayerInto(AlternatingImageStorage & compositionIntermediateStorage,Layer * srcLayer,std::uint8_t * dstBuffer,std::uint32_t dstBufferWidth,std::uint32_t dstBufferHeight,std::uint32_t dstBufferStrideBytes,std::uint32_t dstBufferBytesPerPixel)867 HWC3::Error GuestFrameComposer::composeLayerInto(
868     AlternatingImageStorage& compositionIntermediateStorage,
869     Layer* srcLayer,                     //
870     std::uint8_t* dstBuffer,             //
871     std::uint32_t dstBufferWidth,        //
872     std::uint32_t dstBufferHeight,       //
873     std::uint32_t dstBufferStrideBytes,  //
874     std::uint32_t dstBufferBytesPerPixel) {
875     ATRACE_CALL();
876 
877     libyuv::RotationMode rotation = GetRotationFromTransform(srcLayer->getTransform());
878 
879     common::Rect srcLayerCrop = srcLayer->getSourceCropInt();
880     common::Rect srcLayerDisplayFrame = srcLayer->getDisplayFrame();
881 
882     BufferSpec srcLayerSpec;
883 
884     std::optional<GrallocBuffer> srcBufferOpt;
885     std::optional<GrallocBufferView> srcBufferViewOpt;
886 
887     const auto srcLayerCompositionType = srcLayer->getCompositionType();
888     if (srcLayerCompositionType == Composition::DEVICE) {
889         srcBufferOpt = mGralloc.Import(srcLayer->waitAndGetBuffer());
890         if (!srcBufferOpt) {
891             ALOGE("%s: failed to import layer buffer.", __FUNCTION__);
892             return HWC3::Error::NoResources;
893         }
894         GrallocBuffer& srcBuffer = *srcBufferOpt;
895 
896         srcBufferViewOpt = srcBuffer.Lock();
897         if (!srcBufferViewOpt) {
898             ALOGE("%s: failed to lock import layer buffer.", __FUNCTION__);
899             return HWC3::Error::NoResources;
900         }
901         GrallocBufferView& srcBufferView = *srcBufferViewOpt;
902 
903         auto srcLayerSpecOpt = GetBufferSpec(srcBuffer, srcBufferView, srcLayerCrop);
904         if (!srcLayerSpecOpt) {
905             return HWC3::Error::NoResources;
906         }
907 
908         srcLayerSpec = *srcLayerSpecOpt;
909     } else if (srcLayerCompositionType == Composition::SOLID_COLOR) {
910         // srcLayerSpec not used by `needsFill` below.
911     }
912 
913     // TODO(jemoreira): Remove the hardcoded fomat.
914     bool needsFill = srcLayerCompositionType == Composition::SOLID_COLOR;
915     bool needsConversion = srcLayerCompositionType == Composition::DEVICE &&
916                            srcLayerSpec.drmFormat != DRM_FORMAT_XBGR8888 &&
917                            srcLayerSpec.drmFormat != DRM_FORMAT_ABGR8888;
918     bool needsScaling = LayerNeedsScaling(*srcLayer);
919     bool needsRotation = rotation != libyuv::kRotate0;
920     bool needsTranspose = needsRotation && rotation != libyuv::kRotate180;
921     bool needsVFlip = GetVFlipFromTransform(srcLayer->getTransform());
922     bool needsAttenuation = LayerNeedsAttenuation(*srcLayer);
923     bool needsBlending = LayerNeedsBlending(*srcLayer);
924     bool needsCopy = !(needsConversion || needsScaling || needsRotation || needsVFlip ||
925                        needsAttenuation || needsBlending);
926 
927     BufferSpec dstLayerSpec(
928         dstBuffer,
929         /*buffer_ycbcr=*/std::nullopt, dstBufferWidth, dstBufferHeight,
930         static_cast<uint32_t>(srcLayerDisplayFrame.left),
931         static_cast<uint32_t>(srcLayerDisplayFrame.top),
932         static_cast<uint32_t>(srcLayerDisplayFrame.right - srcLayerDisplayFrame.left),
933         static_cast<uint32_t>(srcLayerDisplayFrame.bottom - srcLayerDisplayFrame.top),
934         DRM_FORMAT_XBGR8888, dstBufferStrideBytes, dstBufferBytesPerPixel);
935 
936     // Add the destination layer to the bottom of the buffer stack
937     std::vector<BufferSpec> dstBufferStack(1, dstLayerSpec);
938 
939     // If more than operation is to be performed, a temporary buffer is needed for
940     // each additional operation
941 
942     // N operations need N destination buffers, the destination layer (the
943     // framebuffer) is one of them, so only N-1 temporary buffers are needed.
944     // Vertical flip is not taken into account because it can be done together
945     // with any other operation.
946     int neededIntermediateImages = (needsFill ? 1 : 0) + (needsConversion ? 1 : 0) +
947                                    (needsScaling ? 1 : 0) + (needsRotation ? 1 : 0) +
948                                    (needsAttenuation ? 1 : 0) + (needsBlending ? 1 : 0) +
949                                    (needsCopy ? 1 : 0) - 1;
950 
951     uint32_t mScratchBufferWidth =
952         static_cast<uint32_t>(srcLayerDisplayFrame.right - srcLayerDisplayFrame.left);
953     uint32_t mScratchBufferHeight =
954         static_cast<uint32_t>(srcLayerDisplayFrame.bottom - srcLayerDisplayFrame.top);
955     uint32_t mScratchBufferStrideBytes =
956         AlignToPower2(mScratchBufferWidth * dstBufferBytesPerPixel, 4);
957     uint32_t mScratchBufferSizeBytes = mScratchBufferHeight * mScratchBufferStrideBytes;
958 
959     for (uint32_t i = 0; i < neededIntermediateImages; i++) {
960         BufferSpec mScratchBufferspec(
961             compositionIntermediateStorage.getRotatingScratchBuffer(mScratchBufferSizeBytes, i),
962             mScratchBufferWidth, mScratchBufferHeight, mScratchBufferStrideBytes);
963         dstBufferStack.push_back(mScratchBufferspec);
964     }
965 
966     // Filling, conversion, and scaling should always be the first operations, so
967     // that every other operation works on equally sized frames (guaranteed to fit
968     // in the scratch buffers) in a common format.
969 
970     if (needsFill) {
971         BufferSpec& dstBufferSpec = dstBufferStack.back();
972 
973         int retval = DoFill(dstBufferSpec, srcLayer->getColor());
974         if (retval) {
975             ALOGE("Got error code %d from DoFill function", retval);
976         }
977 
978         srcLayerSpec = dstBufferSpec;
979         dstBufferStack.pop_back();
980     }
981 
982     // TODO(jemoreira): We are converting to ARGB as the first step under the
983     // assumption that scaling ARGB is faster than scaling I420 (the most common).
984     // This should be confirmed with testing.
985     if (needsConversion) {
986         BufferSpec& dstBufferSpec = dstBufferStack.back();
987         if (needsScaling || needsTranspose) {
988             // If a rotation or a scaling operation are needed the dimensions at the
989             // top of the buffer stack are wrong (wrong sizes for scaling, swapped
990             // width and height for 90 and 270 rotations).
991             // Make width and height match the crop sizes on the source
992             uint32_t srcWidth = srcLayerSpec.cropWidth;
993             uint32_t srcHeight = srcLayerSpec.cropHeight;
994             uint32_t dst_stride_bytes = AlignToPower2(srcWidth * dstBufferBytesPerPixel, 4);
995             uint32_t neededSize = dst_stride_bytes * srcHeight;
996             dstBufferSpec.width = srcWidth;
997             dstBufferSpec.height = srcHeight;
998             // Adjust the stride accordingly
999             dstBufferSpec.strideBytes = dst_stride_bytes;
1000             // Crop sizes also need to be adjusted
1001             dstBufferSpec.cropWidth = srcWidth;
1002             dstBufferSpec.cropHeight = srcHeight;
1003             // cropX and y are fine at 0, format is already set to match destination
1004 
1005             // In case of a scale, the source frame may be bigger than the default tmp
1006             // buffer size
1007             dstBufferSpec.buffer =
1008                 compositionIntermediateStorage.getSpecialScratchBuffer(neededSize);
1009         }
1010 
1011         int retval = DoConversion(srcLayerSpec, dstBufferSpec, needsVFlip);
1012         if (retval) {
1013             ALOGE("Got error code %d from DoConversion function", retval);
1014         }
1015         needsVFlip = false;
1016         srcLayerSpec = dstBufferSpec;
1017         dstBufferStack.pop_back();
1018     }
1019 
1020     if (needsScaling) {
1021         BufferSpec& dstBufferSpec = dstBufferStack.back();
1022         if (needsTranspose) {
1023             // If a rotation is needed, the temporary buffer has the correct size but
1024             // needs to be transposed and have its stride updated accordingly. The
1025             // crop sizes also needs to be transposed, but not the x and y since they
1026             // are both zero in a temporary buffer (and it is a temporary buffer
1027             // because a rotation will be performed next).
1028             std::swap(dstBufferSpec.width, dstBufferSpec.height);
1029             std::swap(dstBufferSpec.cropWidth, dstBufferSpec.cropHeight);
1030             // TODO (jemoreira): Aligment (To align here may cause the needed size to
1031             // be bigger than the buffer, so care should be taken)
1032             dstBufferSpec.strideBytes = dstBufferSpec.width * dstBufferBytesPerPixel;
1033         }
1034         int retval = DoScaling(srcLayerSpec, dstBufferSpec, needsVFlip);
1035         needsVFlip = false;
1036         if (retval) {
1037             ALOGE("Got error code %d from DoScaling function", retval);
1038         }
1039         srcLayerSpec = dstBufferSpec;
1040         dstBufferStack.pop_back();
1041     }
1042 
1043     if (needsRotation) {
1044         int retval = DoRotation(srcLayerSpec, dstBufferStack.back(), rotation, needsVFlip);
1045         needsVFlip = false;
1046         if (retval) {
1047             ALOGE("Got error code %d from DoTransform function", retval);
1048         }
1049         srcLayerSpec = dstBufferStack.back();
1050         dstBufferStack.pop_back();
1051     }
1052 
1053     if (needsAttenuation) {
1054         int retval = DoAttenuation(srcLayerSpec, dstBufferStack.back(), needsVFlip);
1055         needsVFlip = false;
1056         if (retval) {
1057             ALOGE("Got error code %d from DoBlending function", retval);
1058         }
1059         srcLayerSpec = dstBufferStack.back();
1060         dstBufferStack.pop_back();
1061     }
1062 
1063     if (needsCopy) {
1064         int retval = DoCopy(srcLayerSpec, dstBufferStack.back(), needsVFlip);
1065         needsVFlip = false;
1066         if (retval) {
1067             ALOGE("Got error code %d from DoBlending function", retval);
1068         }
1069         srcLayerSpec = dstBufferStack.back();
1070         dstBufferStack.pop_back();
1071     }
1072 
1073     // Blending (if needed) should always be the last operation, so that it reads
1074     // and writes in the destination layer and not some temporary buffer.
1075     if (needsBlending) {
1076         int retval = DoBlending(srcLayerSpec, dstBufferStack.back(), needsVFlip);
1077         needsVFlip = false;
1078         if (retval) {
1079             ALOGE("Got error code %d from DoBlending function", retval);
1080         }
1081         // Don't need to assign destination to source in the last one
1082         dstBufferStack.pop_back();
1083     }
1084 
1085     return HWC3::Error::None;
1086 }
1087 
1088 namespace {
1089 
1090 // Returns a color matrix that can be used with libyuv by converting values
1091 // in -1 to 1 into -64 to 64 and transposing.
ToLibyuvColorMatrix(const std::array<float,16> & in)1092 std::array<std::int8_t, 16> ToLibyuvColorMatrix(const std::array<float, 16>& in) {
1093     std::array<std::int8_t, 16> out;
1094 
1095     for (size_t r = 0; r < 4; r++) {
1096         for (size_t c = 0; c < 4; c++) {
1097             size_t indexIn = (4 * r) + c;
1098             size_t indexOut = (4 * c) + r;
1099 
1100             out[indexOut] = static_cast<std::int8_t>(
1101                 std::max(-128, std::min(127, static_cast<int>(in[indexIn] * 64.0f + 0.5f))));
1102         }
1103     }
1104 
1105     return out;
1106 }
1107 
1108 }  // namespace
1109 
applyColorTransformToRGBA(const std::array<float,16> & transfromMatrix,std::uint8_t * buffer,std::uint32_t bufferWidth,std::uint32_t bufferHeight,std::uint32_t bufferStrideBytes)1110 HWC3::Error GuestFrameComposer::applyColorTransformToRGBA(
1111     const std::array<float, 16>& transfromMatrix,  //
1112     std::uint8_t* buffer,                          //
1113     std::uint32_t bufferWidth,                     //
1114     std::uint32_t bufferHeight,                    //
1115     std::uint32_t bufferStrideBytes) {
1116     ATRACE_CALL();
1117 
1118     const auto transformMatrixLibyuv = ToLibyuvColorMatrix(transfromMatrix);
1119     libyuv::ARGBColorMatrix(buffer, static_cast<int>(bufferStrideBytes),  //
1120                             buffer, static_cast<int>(bufferStrideBytes),  //
1121                             transformMatrixLibyuv.data(),                 //
1122                             static_cast<int>(bufferWidth),                //
1123                             static_cast<int>(bufferHeight));
1124 
1125     return HWC3::Error::None;
1126 }
1127 
1128 }  // namespace aidl::android::hardware::graphics::composer3::impl
1129