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