• 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/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