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