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