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