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