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