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