• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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