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