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