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