1 /*
2 * Copyright (C) 2016 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 "guest/hals/hwcomposer/common/cpu_composer.h"
18
19 #include <algorithm>
20 #include <cstdlib>
21 #include <utility>
22 #include <vector>
23
24 #include <drm_fourcc.h>
25 #include <hardware/hwcomposer.h>
26 #include <hardware/hwcomposer_defs.h>
27 #include <libyuv.h>
28 #include <log/log.h>
29
30 #include "common/libs/utils/size_utils.h"
31 #include "guest/hals/hwcomposer/common/drm_utils.h"
32 #include "guest/hals/hwcomposer/common/geometry_utils.h"
33
34 namespace cvd {
35
36 namespace {
37
LayerNeedsScaling(const hwc_layer_1_t & layer)38 bool LayerNeedsScaling(const hwc_layer_1_t& layer) {
39 int from_w = layer.sourceCrop.right - layer.sourceCrop.left;
40 int from_h = layer.sourceCrop.bottom - layer.sourceCrop.top;
41 int to_w = layer.displayFrame.right - layer.displayFrame.left;
42 int to_h = layer.displayFrame.bottom - layer.displayFrame.top;
43
44 bool not_rot_scale = from_w != to_w || from_h != to_h;
45 bool rot_scale = from_w != to_h || from_h != to_w;
46
47 bool needs_rot = layer.transform & HAL_TRANSFORM_ROT_90;
48
49 return needs_rot ? rot_scale : not_rot_scale;
50 }
51
LayerNeedsBlending(const hwc_layer_1_t & layer)52 bool LayerNeedsBlending(const hwc_layer_1_t& layer) {
53 return layer.blending != HWC_BLENDING_NONE;
54 }
55
LayerNeedsAttenuation(const hwc_layer_1_t & layer)56 bool LayerNeedsAttenuation(const hwc_layer_1_t& layer) {
57 return layer.blending == HWC_BLENDING_COVERAGE;
58 }
59
60 struct BufferSpec;
61 typedef int (*ConverterFunction)(const BufferSpec& src, const BufferSpec& dst,
62 bool v_flip);
63 int DoCopy(const BufferSpec& src, const BufferSpec& dst, bool v_flip);
64 int ConvertFromYV12(const BufferSpec& src, const BufferSpec& dst, bool v_flip);
65
GetConverterForDrmFormat(uint32_t drm_format)66 ConverterFunction GetConverterForDrmFormat(uint32_t drm_format) {
67 switch (drm_format) {
68 case DRM_FORMAT_ABGR8888:
69 case DRM_FORMAT_XBGR8888:
70 return &DoCopy;
71 case DRM_FORMAT_YVU420:
72 return &ConvertFromYV12;
73 }
74 ALOGW("Unsupported format: %d(%s), returning null converter",
75 drm_format, GetDrmFormatString(drm_format));
76 return nullptr;
77 }
78
IsDrmFormatSupported(uint32_t drm_format)79 bool IsDrmFormatSupported(uint32_t drm_format) {
80 return GetConverterForDrmFormat(drm_format) != nullptr;
81 }
82
83 /*******************************************************************************
84 Libyuv's convert functions only allow the combination of any rotation (multiple
85 of 90 degrees) and a vertical flip, but not horizontal flips.
86 Surfaceflinger's transformations are expressed in terms of a vertical flip, a
87 horizontal flip and/or a single 90 degrees clockwise rotation (see
88 NATIVE_WINDOW_TRANSFORM_HINT documentation on system/window.h for more insight).
89 The following code allows to turn a horizontal flip into a 180 degrees rotation
90 and a vertical flip.
91 *******************************************************************************/
GetRotationFromTransform(uint32_t transform)92 libyuv::RotationMode GetRotationFromTransform(uint32_t transform) {
93 uint32_t rotation =
94 (transform & HAL_TRANSFORM_ROT_90) ? 1 : 0; // 1 * ROT90 bit
95 rotation += (transform & HAL_TRANSFORM_FLIP_H) ? 2 : 0; // 2 * VFLIP bit
96 return static_cast<libyuv::RotationMode>(90 * rotation);
97 }
98
GetVFlipFromTransform(uint32_t transform)99 bool GetVFlipFromTransform(uint32_t transform) {
100 // vertical flip xor horizontal flip
101 return ((transform & HAL_TRANSFORM_FLIP_V) >> 1) ^
102 (transform & HAL_TRANSFORM_FLIP_H);
103 }
104
105 struct BufferSpec {
106 uint8_t* buffer;
107 std::optional<android_ycbcr> buffer_ycbcr;
108 int width;
109 int height;
110 int crop_x;
111 int crop_y;
112 int crop_width;
113 int crop_height;
114 uint32_t drm_format;
115 int stride_bytes;
116 int sample_bytes;
117
BufferSpeccvd::__anonb73405500111::BufferSpec118 BufferSpec(uint8_t* buffer,
119 std::optional<android_ycbcr> buffer_ycbcr,
120 int width,
121 int height,
122 int crop_x,
123 int crop_y,
124 int crop_width,
125 int crop_height,
126 uint32_t drm_format,
127 int stride_bytes,
128 int sample_bytes)
129 : buffer(buffer),
130 buffer_ycbcr(buffer_ycbcr),
131 width(width),
132 height(height),
133 crop_x(crop_x),
134 crop_y(crop_y),
135 crop_width(crop_width),
136 crop_height(crop_height),
137 drm_format(drm_format),
138 stride_bytes(stride_bytes),
139 sample_bytes(sample_bytes) {}
140
BufferSpeccvd::__anonb73405500111::BufferSpec141 BufferSpec(uint8_t* buffer,
142 int width,
143 int height,
144 int stride_bytes)
145 : BufferSpec(buffer,
146 /*buffer_ycbcr=*/std::nullopt,
147 width,
148 height,
149 /*crop_x=*/0,
150 /*crop_y=*/0,
151 /*crop_width=*/width,
152 /*crop_height=*/height,
153 /*drm_format=*/DRM_FORMAT_ABGR8888,
154 stride_bytes,
155 /*sample_bytes=*/4) {}
156
157 };
158
ConvertFromYV12(const BufferSpec & src,const BufferSpec & dst,bool v_flip)159 int ConvertFromYV12(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
160 // The following calculation of plane offsets and alignments are based on
161 // swiftshader's Sampler::setTextureLevel() implementation
162 // (Renderer/Sampler.cpp:225)
163
164 auto& src_buffer_ycbcr_opt = src.buffer_ycbcr;
165 if (!src_buffer_ycbcr_opt) {
166 ALOGE("%s called on non ycbcr buffer", __FUNCTION__);
167 return -1;
168 }
169 auto& src_buffer_ycbcr = *src_buffer_ycbcr_opt;
170
171 // The libyuv::I420ToARGB() function is for tri-planar.
172 if (src_buffer_ycbcr.chroma_step != 1) {
173 ALOGE("%s called with bad chroma step", __FUNCTION__);
174 return -1;
175 }
176
177 uint8_t* src_y = reinterpret_cast<uint8_t*>(src_buffer_ycbcr.y);
178 int stride_y = src_buffer_ycbcr.ystride;
179 uint8_t* src_u = reinterpret_cast<uint8_t*>(src_buffer_ycbcr.cb);
180 int stride_u = src_buffer_ycbcr.cstride;
181 uint8_t* src_v = reinterpret_cast<uint8_t*>(src_buffer_ycbcr.cr);
182 int stride_v = src_buffer_ycbcr.cstride;
183
184 // Adjust for crop
185 src_y += src.crop_y * stride_y + src.crop_x;
186 src_v += (src.crop_y / 2) * stride_v + (src.crop_x / 2);
187 src_u += (src.crop_y / 2) * stride_u + (src.crop_x / 2);
188 uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
189 dst.crop_x * dst.sample_bytes;
190
191 // YV12 is the same as I420, with the U and V planes swapped
192 return libyuv::I420ToARGB(src_y, stride_y,
193 src_v, stride_v,
194 src_u, stride_u,
195 dst_buffer, dst.stride_bytes,
196 dst.crop_width,
197 v_flip ? -dst.crop_height : dst.crop_height);
198 }
199
DoConversion(const BufferSpec & src,const BufferSpec & dst,bool v_flip)200 int DoConversion(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
201 return (*GetConverterForDrmFormat(src.drm_format))(src, dst, v_flip);
202 }
203
DoCopy(const BufferSpec & src,const BufferSpec & dst,bool v_flip)204 int DoCopy(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
205 // Point to the upper left corner of the crop rectangle
206 uint8_t* src_buffer = src.buffer + src.crop_y * src.stride_bytes +
207 src.crop_x * src.sample_bytes;
208 uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
209 dst.crop_x * dst.sample_bytes;
210 int width = src.crop_width;
211 int height = src.crop_height;
212
213 if (v_flip) {
214 height = -height;
215 }
216
217 // HAL formats are named based on the order of the pixel componets on the
218 // byte stream, while libyuv formats are named based on the order of those
219 // pixel components in an integer written from left to right. So
220 // libyuv::FOURCC_ARGB is equivalent to HAL_PIXEL_FORMAT_BGRA_8888.
221 auto ret = libyuv::ARGBCopy(src_buffer, src.stride_bytes,
222 dst_buffer, dst.stride_bytes,
223 width, height);
224 return ret;
225 }
226
DoRotation(const BufferSpec & src,const BufferSpec & dst,libyuv::RotationMode rotation,bool v_flip)227 int DoRotation(const BufferSpec& src, const BufferSpec& dst,
228 libyuv::RotationMode rotation, bool v_flip) {
229 // Point to the upper left corner of the crop rectangles
230 uint8_t* src_buffer = src.buffer + src.crop_y * src.stride_bytes +
231 src.crop_x * src.sample_bytes;
232 uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
233 dst.crop_x * dst.sample_bytes;
234 int width = src.crop_width;
235 int height = src.crop_height;
236
237 if (v_flip) {
238 height = -height;
239 }
240
241 return libyuv::ARGBRotate(src_buffer, src.stride_bytes,
242 dst_buffer, dst.stride_bytes,
243 width, height, rotation);
244 }
245
DoScaling(const BufferSpec & src,const BufferSpec & dst,bool v_flip)246 int DoScaling(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
247 // Point to the upper left corner of the crop rectangles
248 uint8_t* src_buffer = src.buffer + src.crop_y * src.stride_bytes +
249 src.crop_x * src.sample_bytes;
250 uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
251 dst.crop_x * dst.sample_bytes;
252 int src_width = src.crop_width;
253 int src_height = src.crop_height;
254 int dst_width = dst.crop_width;
255 int dst_height = dst.crop_height;
256
257 if (v_flip) {
258 src_height = -src_height;
259 }
260
261 return libyuv::ARGBScale(src_buffer, src.stride_bytes, src_width, src_height,
262 dst_buffer, dst.stride_bytes, dst_width, dst_height,
263 libyuv::kFilterBilinear);
264 }
265
DoAttenuation(const BufferSpec & src,const BufferSpec & dst,bool v_flip)266 int DoAttenuation(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
267 // Point to the upper left corner of the crop rectangles
268 uint8_t* src_buffer = src.buffer + src.crop_y * src.stride_bytes +
269 src.crop_x * src.sample_bytes;
270 uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
271 dst.crop_x * dst.sample_bytes;
272 int width = dst.crop_width;
273 int height = dst.crop_height;
274
275 if (v_flip) {
276 height = -height;
277 }
278
279 return libyuv::ARGBAttenuate(src_buffer, src.stride_bytes,
280 dst_buffer, dst.stride_bytes,
281 width, height);
282 }
283
DoBlending(const BufferSpec & src,const BufferSpec & dst,bool v_flip)284 int DoBlending(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
285 // Point to the upper left corner of the crop rectangles
286 uint8_t* src_buffer = src.buffer + src.crop_y * src.stride_bytes +
287 src.crop_x * src.sample_bytes;
288 uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride_bytes +
289 dst.crop_x * dst.sample_bytes;
290 int width = dst.crop_width;
291 int height = dst.crop_height;
292
293 if (v_flip) {
294 height = -height;
295 }
296
297 // libyuv's ARGB format is hwcomposer's BGRA format, since blending only cares
298 // for the position of alpha in the pixel and not the position of the colors
299 // this function is perfectly usable.
300 return libyuv::ARGBBlend(src_buffer, src.stride_bytes,
301 dst_buffer, dst.stride_bytes,
302 dst_buffer, dst.stride_bytes,
303 width, height);
304 }
305
GetBufferSpec(GrallocBuffer & buffer,const hwc_rect_t & buffer_crop)306 std::optional<BufferSpec> GetBufferSpec(GrallocBuffer& buffer,
307 const hwc_rect_t& buffer_crop) {
308 auto buffer_format_opt = buffer.GetDrmFormat();
309 if (!buffer_format_opt) {
310 ALOGE("Failed to get gralloc buffer format.");
311 return std::nullopt;
312 }
313 uint32_t buffer_format = *buffer_format_opt;
314
315 auto buffer_width_opt = buffer.GetWidth();
316 if (!buffer_width_opt) {
317 ALOGE("Failed to get gralloc buffer width.");
318 return std::nullopt;
319 }
320 uint32_t buffer_width = *buffer_width_opt;
321
322 auto buffer_height_opt = buffer.GetHeight();
323 if (!buffer_height_opt) {
324 ALOGE("Failed to get gralloc buffer height.");
325 return std::nullopt;
326 }
327 uint32_t buffer_height = *buffer_height_opt;
328
329 uint8_t* buffer_data = nullptr;
330 uint32_t buffer_stride_bytes = 0;
331 std::optional<android_ycbcr> buffer_ycbcr_data;
332
333 if (buffer_format == DRM_FORMAT_NV12 ||
334 buffer_format == DRM_FORMAT_NV21 ||
335 buffer_format == DRM_FORMAT_YVU420) {
336 buffer_ycbcr_data = buffer.LockYCbCr();
337 if (!buffer_ycbcr_data) {
338 ALOGE("%s failed to lock gralloc buffer.", __FUNCTION__);
339 return std::nullopt;
340 }
341 } else {
342 auto buffer_data_opt = buffer.Lock();
343 if (!buffer_data_opt) {
344 ALOGE("%s failed to lock gralloc buffer.", __FUNCTION__);
345 return std::nullopt;
346 }
347 buffer_data = reinterpret_cast<uint8_t*>(*buffer_data_opt);
348
349 auto buffer_stride_bytes_opt = buffer.GetMonoPlanarStrideBytes();
350 if (!buffer_stride_bytes_opt) {
351 ALOGE("%s failed to get plane stride.", __FUNCTION__);
352 return std::nullopt;
353 }
354 buffer_stride_bytes = *buffer_stride_bytes_opt;
355 }
356
357 return BufferSpec(
358 buffer_data,
359 buffer_ycbcr_data,
360 buffer_width,
361 buffer_height,
362 buffer_crop.left,
363 buffer_crop.top,
364 buffer_crop.right - buffer_crop.left,
365 buffer_crop.bottom - buffer_crop.top,
366 buffer_format,
367 buffer_stride_bytes,
368 GetDrmFormatBytesPerPixel(buffer_format));
369 }
370
371 } // namespace
372
CanCompositeLayer(const hwc_layer_1_t & layer)373 bool CpuComposer::CanCompositeLayer(const hwc_layer_1_t& layer) {
374 buffer_handle_t buffer_handle = layer.handle;
375 if (buffer_handle == nullptr) {
376 ALOGW("%s received a layer with a null handle", __FUNCTION__);
377 return false;
378 }
379
380 auto buffer_opt = gralloc_.Import(buffer_handle);
381 if (!buffer_opt) {
382 ALOGE("Failed to import layer buffer.");
383 return false;
384 }
385 GrallocBuffer& buffer = *buffer_opt;
386
387 auto buffer_format_opt = buffer.GetDrmFormat();
388 if (!buffer_format_opt) {
389 ALOGE("Failed to get layer buffer format.");
390 return false;
391 }
392 uint32_t buffer_format = *buffer_format_opt;
393
394 if (!IsDrmFormatSupported(buffer_format)) {
395 ALOGD("Unsupported pixel format: 0x%x, doing software composition instead",
396 buffer_format);
397 return false;
398 }
399 return true;
400 }
401
CompositeLayer(hwc_layer_1_t * src_layer,int buffer_idx)402 void CpuComposer::CompositeLayer(hwc_layer_1_t* src_layer, int buffer_idx) {
403 libyuv::RotationMode rotation =
404 GetRotationFromTransform(src_layer->transform);
405
406 auto src_imported_buffer_opt = gralloc_.Import(src_layer->handle);
407 if (!src_imported_buffer_opt) {
408 ALOGE("Failed to import layer buffer.");
409 return;
410 }
411 GrallocBuffer& src_imported_buffer = *src_imported_buffer_opt;
412
413 auto src_layer_spec_opt = GetBufferSpec(src_imported_buffer, src_layer->sourceCrop);
414 if (!src_layer_spec_opt) {
415 return;
416 }
417 BufferSpec src_layer_spec = *src_layer_spec_opt;
418
419 // TODO(jemoreira): Remove the hardcoded fomat.
420 bool needs_conversion = src_layer_spec.drm_format != DRM_FORMAT_XBGR8888;
421 bool needs_scaling = LayerNeedsScaling(*src_layer);
422 bool needs_rotation = rotation != libyuv::kRotate0;
423 bool needs_transpose = needs_rotation && rotation != libyuv::kRotate180;
424 bool needs_vflip = GetVFlipFromTransform(src_layer->transform);
425 bool needs_attenuation = LayerNeedsAttenuation(*src_layer);
426 bool needs_blending = LayerNeedsBlending(*src_layer);
427 bool needs_copy = !(needs_conversion || needs_scaling || needs_rotation ||
428 needs_vflip || needs_attenuation || needs_blending);
429
430 uint8_t* dst_buffer =
431 reinterpret_cast<uint8_t*>(screen_view_->GetBuffer(buffer_idx));
432
433 BufferSpec dst_layer_spec(
434 dst_buffer,
435 /*buffer_ycbcr=*/std::nullopt,
436 screen_view_->x_res(),
437 screen_view_->y_res(),
438 src_layer->displayFrame.left,
439 src_layer->displayFrame.top,
440 src_layer->displayFrame.right - src_layer->displayFrame.left,
441 src_layer->displayFrame.bottom - src_layer->displayFrame.top,
442 DRM_FORMAT_XBGR8888,
443 screen_view_->line_length(),
444 4);
445
446 // Add the destination layer to the bottom of the buffer stack
447 std::vector<BufferSpec> dest_buffer_stack(1, dst_layer_spec);
448
449 // If more than operation is to be performed, a temporary buffer is needed for
450 // each additional operation
451
452 // N operations need N destination buffers, the destination layer (the
453 // framebuffer) is one of them, so only N-1 temporary buffers are needed.
454 // Vertical flip is not taken into account because it can be done together
455 // with any other operation.
456 int needed_tmp_buffers = (needs_conversion ? 1 : 0) +
457 (needs_scaling ? 1 : 0) + (needs_rotation ? 1 : 0) +
458 (needs_attenuation ? 1 : 0) +
459 (needs_blending ? 1 : 0) + (needs_copy ? 1 : 0) - 1;
460
461 int tmp_buffer_width =
462 src_layer->displayFrame.right - src_layer->displayFrame.left;
463 int tmp_buffer_height =
464 src_layer->displayFrame.bottom - src_layer->displayFrame.top;
465 int tmp_buffer_stride_bytes =
466 cvd::AlignToPowerOf2(tmp_buffer_width * screen_view_->bytes_per_pixel(), 4);
467
468 for (int i = 0; i < needed_tmp_buffers; i++) {
469 BufferSpec tmp_buffer_spec(
470 RotateTmpBuffer(i),
471 tmp_buffer_width,
472 tmp_buffer_height,
473 tmp_buffer_stride_bytes);
474 dest_buffer_stack.push_back(tmp_buffer_spec);
475 }
476
477 // Conversion and scaling should always be the first operations, so that every
478 // other operation works on equally sized frames (garanteed to fit in the tmp
479 // buffers)
480
481 // TODO(jemoreira): We are converting to ARGB as the first step under the
482 // assumption that scaling ARGB is faster than scaling I420 (the most common).
483 // This should be confirmed with testing.
484 if (needs_conversion) {
485 BufferSpec& dst_buffer_spec = dest_buffer_stack.back();
486 if (needs_scaling || needs_transpose) {
487 // If a rotation or a scaling operation are needed the dimensions at the
488 // top of the buffer stack are wrong (wrong sizes for scaling, swapped
489 // width and height for 90 and 270 rotations).
490 // Make width and height match the crop sizes on the source
491 int src_width = src_layer_spec.crop_width;
492 int src_height = src_layer_spec.crop_height;
493 int dst_stride_bytes =
494 cvd::AlignToPowerOf2(src_width * screen_view_->bytes_per_pixel(), 4);
495 size_t needed_size = dst_stride_bytes * src_height;
496 dst_buffer_spec.width = src_width;
497 dst_buffer_spec.height = src_height;
498 // Adjust the stride accordingly
499 dst_buffer_spec.stride_bytes = dst_stride_bytes;
500 // Crop sizes also need to be adjusted
501 dst_buffer_spec.crop_width = src_width;
502 dst_buffer_spec.crop_height = src_height;
503 // crop_x and y are fine at 0, format is already set to match destination
504
505 // In case of a scale, the source frame may be bigger than the default tmp
506 // buffer size
507 if (needed_size > tmp_buffer_.size() / kNumTmpBufferPieces) {
508 dst_buffer_spec.buffer = GetSpecialTmpBuffer(needed_size);
509 }
510 }
511
512 int retval = DoConversion(src_layer_spec, dst_buffer_spec, needs_vflip);
513 if (retval) {
514 ALOGE("Got error code %d from DoConversion function", retval);
515 }
516 needs_vflip = false;
517 src_layer_spec = dst_buffer_spec;
518 dest_buffer_stack.pop_back();
519 }
520
521 if (needs_scaling) {
522 BufferSpec& dst_buffer_spec = dest_buffer_stack.back();
523 if (needs_transpose) {
524 // If a rotation is needed, the temporary buffer has the correct size but
525 // needs to be transposed and have its stride updated accordingly. The
526 // crop sizes also needs to be transposed, but not the x and y since they
527 // are both zero in a temporary buffer (and it is a temporary buffer
528 // because a rotation will be performed next).
529 std::swap(dst_buffer_spec.width, dst_buffer_spec.height);
530 std::swap(dst_buffer_spec.crop_width, dst_buffer_spec.crop_height);
531 // TODO (jemoreira): Aligment (To align here may cause the needed size to
532 // be bigger than the buffer, so care should be taken)
533 dst_buffer_spec.stride_bytes =
534 dst_buffer_spec.width * screen_view_->bytes_per_pixel();
535 }
536 int retval = DoScaling(src_layer_spec, dst_buffer_spec, needs_vflip);
537 needs_vflip = false;
538 if (retval) {
539 ALOGE("Got error code %d from DoScaling function", retval);
540 }
541 src_layer_spec = dst_buffer_spec;
542 dest_buffer_stack.pop_back();
543 }
544
545 if (needs_rotation) {
546 int retval = DoRotation(src_layer_spec, dest_buffer_stack.back(), rotation,
547 needs_vflip);
548 needs_vflip = false;
549 if (retval) {
550 ALOGE("Got error code %d from DoTransform function", retval);
551 }
552 src_layer_spec = dest_buffer_stack.back();
553 dest_buffer_stack.pop_back();
554 }
555
556 if (needs_attenuation) {
557 int retval = DoAttenuation(src_layer_spec, dest_buffer_stack.back(),
558 needs_vflip);
559 needs_vflip = false;
560 if (retval) {
561 ALOGE("Got error code %d from DoBlending function", retval);
562 }
563 src_layer_spec = dest_buffer_stack.back();
564 dest_buffer_stack.pop_back();
565 }
566
567 if (needs_copy) {
568 int retval = DoCopy(src_layer_spec, dest_buffer_stack.back(), needs_vflip);
569 needs_vflip = false;
570 if (retval) {
571 ALOGE("Got error code %d from DoBlending function", retval);
572 }
573 src_layer_spec = dest_buffer_stack.back();
574 dest_buffer_stack.pop_back();
575 }
576
577 // Blending (if needed) should always be the last operation, so that it reads
578 // and writes in the destination layer and not some temporary buffer.
579 if (needs_blending) {
580 int retval = DoBlending(src_layer_spec, dest_buffer_stack.back(),
581 needs_vflip);
582 needs_vflip = false;
583 if (retval) {
584 ALOGE("Got error code %d from DoBlending function", retval);
585 }
586 // Don't need to assign destination to source in the last one
587 dest_buffer_stack.pop_back();
588 }
589
590 src_imported_buffer.Unlock();
591 }
592
593 /* static */ const int CpuComposer::kNumTmpBufferPieces = 2;
594
CpuComposer(std::unique_ptr<ScreenView> screen_view)595 CpuComposer::CpuComposer(std::unique_ptr<ScreenView> screen_view)
596 : BaseComposer(std::move(screen_view)),
597 tmp_buffer_(kNumTmpBufferPieces * screen_view_->buffer_size()) {}
598
PrepareLayers(size_t num_layers,hwc_layer_1_t * layers)599 int CpuComposer::PrepareLayers(size_t num_layers, hwc_layer_1_t* layers) {
600 int composited_layers_count = 0;
601
602 // Loop over layers in inverse order of z-index
603 for (size_t layer_index = num_layers; layer_index > 0;) {
604 // Decrement here to be able to compare unsigned integer with 0 in the
605 // loop condition
606 --layer_index;
607 if (IS_TARGET_FRAMEBUFFER(layers[layer_index].compositionType)) {
608 continue;
609 }
610 if (layers[layer_index].flags & HWC_SKIP_LAYER) {
611 continue;
612 }
613 if (layers[layer_index].compositionType == HWC_BACKGROUND) {
614 layers[layer_index].compositionType = HWC_FRAMEBUFFER;
615 continue;
616 }
617 layers[layer_index].compositionType = HWC_OVERLAY;
618 // Hwcomposer cannot draw below software-composed layers, so we need
619 // to mark those HWC_FRAMEBUFFER as well.
620 for (size_t top_idx = layer_index + 1; top_idx < num_layers; ++top_idx) {
621 // layers marked as skip are in a state that makes them unreliable to
622 // read, so it's best to assume they cover the whole screen
623 if (layers[top_idx].flags & HWC_SKIP_LAYER ||
624 (layers[top_idx].compositionType == HWC_FRAMEBUFFER &&
625 LayersOverlap(layers[layer_index], layers[top_idx]))) {
626 layers[layer_index].compositionType = HWC_FRAMEBUFFER;
627 break;
628 }
629 }
630 if (layers[layer_index].compositionType == HWC_OVERLAY &&
631 !CanCompositeLayer(layers[layer_index])) {
632 layers[layer_index].compositionType = HWC_FRAMEBUFFER;
633 }
634 if (layers[layer_index].compositionType == HWC_OVERLAY) {
635 ++composited_layers_count;
636 }
637 }
638 return composited_layers_count;
639 }
640
SetLayers(size_t num_layers,hwc_layer_1_t * layers)641 int CpuComposer::SetLayers(size_t num_layers, hwc_layer_1_t* layers) {
642 int targetFbs = 0;
643 int buffer_idx = screen_view_->NextBuffer();
644
645 // The framebuffer target layer should be composed if at least one layers was
646 // marked HWC_FRAMEBUFFER or if it's the only layer in the composition
647 // (unlikely)
648 bool fb_target = true;
649 for (size_t idx = 0; idx < num_layers; idx++) {
650 if (layers[idx].compositionType == HWC_FRAMEBUFFER) {
651 // At least one was found
652 fb_target = true;
653 break;
654 }
655 if (layers[idx].compositionType == HWC_OVERLAY) {
656 // Not the only layer in the composition
657 fb_target = false;
658 }
659 }
660
661 // When the framebuffer target needs to be composed, it has to go first.
662 if (fb_target) {
663 for (size_t idx = 0; idx < num_layers; idx++) {
664 if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
665 CompositeLayer(&layers[idx], buffer_idx);
666 break;
667 }
668 }
669 }
670
671 for (size_t idx = 0; idx < num_layers; idx++) {
672 if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
673 ++targetFbs;
674 }
675 if (layers[idx].compositionType == HWC_OVERLAY &&
676 !(layers[idx].flags & HWC_SKIP_LAYER)) {
677 CompositeLayer(&layers[idx], buffer_idx);
678 }
679 }
680 if (targetFbs != 1) {
681 ALOGW("Saw %zu layers, posted=%d", num_layers, targetFbs);
682 }
683 screen_view_->Broadcast(buffer_idx);
684 return 0;
685 }
686
RotateTmpBuffer(unsigned int order)687 uint8_t* CpuComposer::RotateTmpBuffer(unsigned int order) {
688 return &tmp_buffer_[(order % kNumTmpBufferPieces) * tmp_buffer_.size() /
689 kNumTmpBufferPieces];
690 }
691
GetSpecialTmpBuffer(size_t needed_size)692 uint8_t* CpuComposer::GetSpecialTmpBuffer(size_t needed_size) {
693 special_tmp_buffer_.resize(needed_size);
694 return &special_tmp_buffer_[0];
695 }
696
697 } // namespace cvd
698