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