1 /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * 17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 * Portions formerly licensed under Apache License, Version 2.0, are re licensed 30 * under section 4 of Apache License, Version 2.0. 31 32 * Copyright (C) 2010 The Android Open Source Project 33 34 * Not a Contribution. 35 36 * Licensed under the Apache License, Version 2.0 (the "License"); 37 * you may not use this file except in compliance with the License. 38 * You may obtain a copy of the License at 39 40 * http://www.apache.org/licenses/LICENSE-2.0 41 42 * Unless required by applicable law or agreed to in writing, software 43 * distributed under the License is distributed on an "AS IS" BASIS, 44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 45 * See the License for the specific language governing permissions and 46 * limitations under the License. 47 */ 48 49 #include <hardware/hardware.h> 50 #include <sync/sync.h> 51 #include <copybit.h> 52 #include <memalloc.h> 53 #include <alloc_controller.h> 54 #include <gr.h> 55 56 #include <utils/constants.h> 57 #include <utils/rect.h> 58 #include <utils/formats.h> 59 #include <algorithm> 60 61 #include "blit_engine_c2d.h" 62 #include "hwc_debugger.h" 63 64 #define __CLASS__ "BlitEngineC2D" 65 66 // TODO(user): Remove pragma after fixing sign conversion errors 67 #if defined(__clang__) 68 #pragma clang diagnostic push 69 #pragma clang diagnostic ignored "-Wsign-conversion" 70 #endif 71 72 namespace sdm { 73 74 75 BlitEngineC2d::RegionIterator::RegionIterator(LayerRectArray rect) { 76 rect_array = rect; 77 r.end = INT(rect.count); 78 r.current = 0; 79 this->next = iterate; 80 } 81 82 int BlitEngineC2d::RegionIterator::iterate(copybit_region_t const *self, copybit_rect_t *rect) { 83 if (!self || !rect) { 84 DLOGE("iterate invalid parameters"); 85 return 0; 86 } 87 88 RegionIterator const *me = static_cast<RegionIterator const*>(self); 89 if (me->r.current != me->r.end) { 90 rect->l = INT(me->rect_array.rect[me->r.current].left); 91 rect->t = INT(me->rect_array.rect[me->r.current].top); 92 rect->r = INT(me->rect_array.rect[me->r.current].right); 93 rect->b = INT(me->rect_array.rect[me->r.current].bottom); 94 me->r.current++; 95 return 1; 96 } 97 return 0; 98 } 99 100 BlitEngineC2d::BlitEngineC2d() { 101 for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) { 102 blit_target_buffer_[i] = NULL; 103 release_fence_fd_[i] = -1; 104 } 105 } 106 107 BlitEngineC2d::~BlitEngineC2d() { 108 if (blit_engine_c2d_) { 109 copybit_close(blit_engine_c2d_); 110 blit_engine_c2d_ = NULL; 111 } 112 FreeBlitTargetBuffers(); 113 } 114 115 int BlitEngineC2d::Init() { 116 hw_module_t const *module; 117 if (hw_get_module("copybit", &module) == 0) { 118 if (copybit_open(module, &blit_engine_c2d_) < 0) { 119 DLOGI("CopyBitC2D Open failed."); 120 return -1; 121 } 122 DLOGI("Opened Copybit Module"); 123 } else { 124 DLOGI("Copybit HW Module not found"); 125 return -1; 126 } 127 128 return 0; 129 } 130 131 void BlitEngineC2d::DeInit() { 132 FreeBlitTargetBuffers(); 133 if (blit_engine_c2d_) { 134 copybit_close(blit_engine_c2d_); 135 blit_engine_c2d_ = NULL; 136 } 137 } 138 139 int BlitEngineC2d::AllocateBlitTargetBuffers(uint32_t width, uint32_t height, uint32_t format, 140 uint32_t usage) { 141 int status = 0; 142 if (width <= 0 || height <= 0) { 143 return false; 144 } 145 146 if (blit_target_buffer_[0]) { 147 // Free and reallocate the buffers if the w/h changes 148 if (INT(width) != blit_target_buffer_[0]->width || 149 INT(height) != blit_target_buffer_[0]->height) { 150 FreeBlitTargetBuffers(); 151 } 152 } 153 154 for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) { 155 if (blit_target_buffer_[i] == NULL) { 156 status = alloc_buffer(&blit_target_buffer_[i], width, height, format, usage); 157 } 158 if (status < 0) { 159 DLOGE("Allocation of Blit target Buffer failed"); 160 FreeBlitTargetBuffers(); 161 break; 162 } 163 } 164 165 return status; 166 } 167 168 void BlitEngineC2d::FreeBlitTargetBuffers() { 169 for (uint32_t i = 0; i < kNumBlitTargetBuffers; i++) { 170 private_handle_t **target_buffer = &blit_target_buffer_[i]; 171 if (*target_buffer) { 172 // Free the valid fence 173 if (release_fence_fd_[i] >= 0) { 174 close(release_fence_fd_[i]); 175 release_fence_fd_[i] = -1; 176 } 177 free_buffer(*target_buffer); 178 *target_buffer = NULL; 179 } 180 } 181 } 182 183 int BlitEngineC2d::ClearTargetBuffer(private_handle_t* hnd, const LayerRect& rect) { 184 int status = 0; 185 copybit_rect_t clear_rect = {INT(rect.left), INT(rect.top), INT(rect.right), INT(rect.bottom)}; 186 187 copybit_image_t buffer; 188 buffer.w = ALIGN((hnd->width), 32); 189 buffer.h = hnd->height; 190 buffer.format = hnd->format; 191 buffer.base = reinterpret_cast<void *>(hnd->base); 192 buffer.handle = reinterpret_cast<native_handle_t *>(hnd); 193 int dst_format_mode = COPYBIT_LINEAR; 194 if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) { 195 dst_format_mode = COPYBIT_UBWC_COMPRESSED; 196 } 197 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_DST_FORMAT_MODE, dst_format_mode); 198 199 status = blit_engine_c2d_->clear(blit_engine_c2d_, &buffer, &clear_rect); 200 return status; 201 } 202 203 void BlitEngineC2d::PostCommit(LayerStack *layer_stack) { 204 int fence_fd = -1; 205 uint32_t count = 0; 206 int fd = -1; 207 208 for (uint32_t i = blit_target_start_index_-2; (i > 0) && (count < num_blit_target_); i--) { 209 Layer *layer = layer_stack->layers.at(i); 210 LayerBuffer &layer_buffer = layer->input_buffer; 211 if (layer->composition == kCompositionBlit) { 212 int index = blit_target_start_index_ + count; 213 layer_buffer.release_fence_fd = 214 layer_stack->layers.at(index)->input_buffer.release_fence_fd; 215 fence_fd = layer_buffer.release_fence_fd; 216 close(layer_buffer.acquire_fence_fd); 217 layer_buffer.acquire_fence_fd = -1; 218 layer_stack->layers.at(index)->input_buffer.release_fence_fd = -1; 219 fd = layer_stack->layers.at(index)->input_buffer.acquire_fence_fd; 220 layer_stack->layers.at(index)->input_buffer.acquire_fence_fd = -1; 221 count++; 222 } 223 } 224 225 if (fd >= 0) { 226 // Close the C2D fence FD 227 close(fd); 228 } 229 SetReleaseFence(fence_fd); 230 } 231 232 // Sync wait to close the previous fd 233 void BlitEngineC2d::SetReleaseFence(int fd) { 234 if (release_fence_fd_[current_blit_target_index_] >= 0) { 235 int ret = -1; 236 ret = sync_wait(release_fence_fd_[current_blit_target_index_], 1000); 237 if (ret < 0) { 238 DLOGE("sync_wait error! errno = %d, err str = %s", errno, strerror(errno)); 239 } 240 close(release_fence_fd_[current_blit_target_index_]); 241 } 242 release_fence_fd_[current_blit_target_index_] = dup(fd); 243 } 244 245 bool BlitEngineC2d::BlitActive() { 246 return blit_active_; 247 } 248 249 void BlitEngineC2d::SetFrameDumpConfig(uint32_t count) { 250 dump_frame_count_ = count; 251 dump_frame_index_ = 0; 252 } 253 254 int BlitEngineC2d::Prepare(LayerStack *layer_stack) { 255 blit_target_start_index_ = 0; 256 257 uint32_t layer_count = UINT32(layer_stack->layers.size()); 258 uint32_t gpu_target_index = layer_count - 1; // default assumption 259 uint32_t i = 0; 260 261 for (; i < layer_count; i++) { 262 Layer *layer = layer_stack->layers.at(i); 263 264 // No 10 bit support for C2D 265 if (Is10BitFormat(layer->input_buffer.format)) { 266 return -1; 267 } 268 269 if (layer->composition == kCompositionGPUTarget) { 270 // Need FBT size for allocating buffers 271 gpu_target_index = i; 272 break; 273 } 274 } 275 276 if ((layer_count - 1) == gpu_target_index) { 277 // No blit target layer 278 return -1; 279 } 280 281 blit_target_start_index_ = ++i; 282 num_blit_target_ = layer_count - blit_target_start_index_; 283 284 LayerBuffer &layer_buffer = layer_stack->layers.at(gpu_target_index)->input_buffer; 285 int fbwidth = INT(layer_buffer.unaligned_width); 286 int fbheight = INT(layer_buffer.unaligned_height); 287 if ((fbwidth < 0) || (fbheight < 0)) { 288 return -1; 289 } 290 291 current_blit_target_index_ = (current_blit_target_index_ + 1) % kNumBlitTargetBuffers; 292 int k = blit_target_start_index_; 293 294 for (uint32_t j = 0; j < num_blit_target_; j++, k++) { 295 Layer *layer = layer_stack->layers.at(k); 296 LayerBuffer &layer_buffer = layer->input_buffer; 297 int aligned_w = 0; 298 int aligned_h = 0; 299 300 // Set the buffer height and width 301 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(fbwidth, fbheight/3, 302 INT(HAL_PIXEL_FORMAT_RGBA_8888), 0, aligned_w, aligned_h); 303 layer_buffer.width = aligned_w; 304 layer_buffer.height = aligned_h; 305 layer_buffer.unaligned_width = fbwidth; 306 layer_buffer.unaligned_height = fbheight/3; 307 308 layer->plane_alpha = 0xFF; 309 layer->blending = kBlendingOpaque; 310 layer->composition = kCompositionBlitTarget; 311 layer->frame_rate = layer_stack->layers.at(gpu_target_index)->frame_rate; 312 } 313 314 return 0; 315 } 316 317 int BlitEngineC2d::PreCommit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) { 318 int status = 0; 319 uint32_t num_app_layers = (uint32_t) content_list->numHwLayers-1; 320 int target_width = 0; 321 int target_height = 0; 322 int target_aligned_width = 0; 323 int target_aligned_height = 0; 324 uint32_t processed_blit = 0; 325 LayerRect dst_rects[kMaxBlitTargetLayers]; 326 bool blit_needed = false; 327 uint32_t usage = 0; 328 329 if (!num_app_layers) { 330 return -1; 331 } 332 333 for (uint32_t i = num_app_layers-1; (i > 0) && (processed_blit < num_blit_target_); i--) { 334 Layer *layer = layer_stack->layers.at(i); 335 if (layer->composition != kCompositionBlit) { 336 continue; 337 } 338 blit_needed = true; 339 layer_stack->flags.attributes_changed = true; 340 341 Layer *blit_layer = layer_stack->layers.at(blit_target_start_index_ + processed_blit); 342 LayerRect &blit_src_rect = blit_layer->src_rect; 343 int width = INT(layer->dst_rect.right - layer->dst_rect.left); 344 int height = INT(layer->dst_rect.bottom - layer->dst_rect.top); 345 int aligned_w = 0; 346 int aligned_h = 0; 347 usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_HW_TEXTURE; 348 if (blit_engine_c2d_->get(blit_engine_c2d_, COPYBIT_UBWC_SUPPORT) > 0) { 349 usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC; 350 } 351 // TODO(user): FrameBuffer is assumed to be RGBA 352 target_width = std::max(target_width, width); 353 target_height += height; 354 355 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width, height, 356 INT(HAL_PIXEL_FORMAT_RGBA_8888), usage, aligned_w, aligned_h); 357 358 target_aligned_width = std::max(target_aligned_width, aligned_w); 359 target_aligned_height += aligned_h; 360 361 // Left will be zero always 362 dst_rects[processed_blit].top = FLOAT(target_aligned_height - aligned_h); 363 dst_rects[processed_blit].right = dst_rects[processed_blit].left + 364 (layer->dst_rect.right - layer->dst_rect.left); 365 dst_rects[processed_blit].bottom = (dst_rects[processed_blit].top + 366 (layer->dst_rect.bottom - layer->dst_rect.top)); 367 blit_src_rect = dst_rects[processed_blit]; 368 processed_blit++; 369 } 370 371 // Allocate a single buffer of RGBA8888 format 372 if (blit_needed && (AllocateBlitTargetBuffers(target_width, target_height, 373 HAL_PIXEL_FORMAT_RGBA_8888, usage) < 0)) { 374 status = -1; 375 return status; 376 } 377 378 if (blit_needed) { 379 for (uint32_t j = 0; j < num_blit_target_; j++) { 380 Layer *layer = layer_stack->layers.at(j + content_list->numHwLayers); 381 private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_]; 382 // Set the fd information 383 layer->input_buffer.width = target_aligned_width; 384 layer->input_buffer.height = target_aligned_height; 385 layer->input_buffer.unaligned_width = target_width; 386 layer->input_buffer.unaligned_height = target_height; 387 if (target_buffer->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) { 388 layer->input_buffer.format = kFormatRGBA8888Ubwc; 389 } 390 layer->input_buffer.planes[0].fd = target_buffer->fd; 391 layer->input_buffer.planes[0].offset = 0; 392 layer->input_buffer.planes[0].stride = target_buffer->width; 393 } 394 } 395 396 return status; 397 } 398 399 int BlitEngineC2d::Commit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) { 400 int fd = -1; 401 int status = 0; 402 bool hybrid_present = false; 403 uint32_t num_app_layers = (uint32_t) content_list->numHwLayers-1; 404 private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_]; 405 blit_active_ = false; 406 407 if (!num_app_layers) { 408 return -1; 409 } 410 411 // if not Blit Targets return 412 for (uint32_t i = 0; i < num_app_layers; i++) { 413 Layer *layer = layer_stack->layers.at(i); 414 if (layer->composition == kCompositionHybrid || layer->composition == kCompositionBlit) { 415 hybrid_present = true; 416 } 417 } 418 419 if (!hybrid_present) { 420 return status; 421 } 422 423 // Clear blit target buffer 424 LayerRect clear_rect; 425 clear_rect.left = 0; 426 clear_rect.top = 0; 427 clear_rect.right = FLOAT(target_buffer->width); 428 clear_rect.bottom = FLOAT(target_buffer->height); 429 ClearTargetBuffer(target_buffer, clear_rect); 430 431 int copybit_layer_count = 0; 432 uint32_t processed_blit = 0; 433 for (uint32_t i = num_app_layers-1; (i > 0) && (processed_blit < num_blit_target_) && 434 (status == 0); i--) { 435 Layer *layer = layer_stack->layers.at(i); 436 if (layer->composition != kCompositionBlit) { 437 continue; 438 } 439 440 for (uint32_t k = 0; k <= i; k++) { 441 Layer *bottom_layer = layer_stack->layers.at(k); 442 LayerBuffer &layer_buffer = bottom_layer->input_buffer; 443 // if layer below the blit layer does not intersect, ignore that layer 444 LayerRect inter_sect = Intersection(layer->dst_rect, bottom_layer->dst_rect); 445 if (bottom_layer->composition != kCompositionHybrid && !IsValid(inter_sect)) { 446 continue; 447 } 448 if (bottom_layer->composition == kCompositionGPU || 449 bottom_layer->composition == kCompositionSDE || 450 bottom_layer->composition == kCompositionGPUTarget) { 451 continue; 452 } 453 454 // For each layer marked as Hybrid, wait for acquire fence and then blit using the C2D 455 if (layer_buffer.acquire_fence_fd >= 0) { 456 // Wait for acquire fence on the App buffers. 457 if (sync_wait(layer_buffer.acquire_fence_fd, 1000) < 0) { 458 DLOGE("sync_wait error!! error no = %d err str = %s", errno, strerror(errno)); 459 } 460 layer_buffer.acquire_fence_fd = -1; 461 } 462 hwc_layer_1_t *hwc_layer = &content_list->hwLayers[k]; 463 LayerRect &src_rect = bottom_layer->blit_regions.at(processed_blit); 464 Layer *blit_layer = layer_stack->layers.at(blit_target_start_index_ + processed_blit); 465 LayerRect dest_rect = blit_layer->src_rect; 466 int ret_val = DrawRectUsingCopybit(hwc_layer, bottom_layer, src_rect, dest_rect); 467 copybit_layer_count++; 468 if (ret_val < 0) { 469 copybit_layer_count = 0; 470 DLOGE("DrawRectUsingCopyBit failed"); 471 status = -1; 472 break; 473 } 474 } 475 processed_blit++; 476 } 477 478 if (copybit_layer_count) { 479 blit_active_ = true; 480 blit_engine_c2d_->flush_get_fence(blit_engine_c2d_, &fd); 481 } 482 483 if (blit_active_) { 484 // dump the render buffer 485 DumpBlitTargetBuffer(fd); 486 487 // Set the fd to the LayerStack BlitTargets fd 488 uint32_t layer_count = UINT32(layer_stack->layers.size()); 489 for (uint32_t k = blit_target_start_index_; k < layer_count; k++) { 490 Layer *layer = layer_stack->layers.at(k); 491 LayerBuffer &layer_buffer = layer->input_buffer; 492 layer_buffer.acquire_fence_fd = fd; 493 } 494 } 495 496 return status; 497 } 498 499 int BlitEngineC2d::DrawRectUsingCopybit(hwc_layer_1_t *hwc_layer, Layer *layer, 500 LayerRect blit_rect, LayerRect blit_dest_Rect) { 501 private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_]; 502 const private_handle_t *hnd = static_cast<const private_handle_t *>(hwc_layer->handle); 503 LayerBuffer &layer_buffer = layer->input_buffer; 504 505 // Set the Copybit Source 506 copybit_image_t src; 507 src.handle = const_cast<native_handle_t *>(hwc_layer->handle); 508 src.w = hnd->width; 509 src.h = hnd->height; 510 src.base = reinterpret_cast<void *>(hnd->base); 511 src.format = hnd->format; 512 src.horiz_padding = 0; 513 src.vert_padding = 0; 514 515 // Copybit source rect 516 copybit_rect_t src_rect = {INT(blit_rect.left), INT(blit_rect.top), INT(blit_rect.right), 517 INT(blit_rect.bottom)}; 518 519 // Copybit destination rect 520 copybit_rect_t dst_rect = {INT(blit_dest_Rect.left), INT(blit_dest_Rect.top), 521 INT(blit_dest_Rect.right), INT(blit_dest_Rect.bottom)}; 522 523 // Copybit destination buffer 524 copybit_image_t dst; 525 dst.handle = static_cast<native_handle_t *>(target_buffer); 526 dst.w = ALIGN(target_buffer->width, 32); 527 dst.h = ALIGN((target_buffer->height), 32); 528 dst.base = reinterpret_cast<void *>(target_buffer->base); 529 dst.format = target_buffer->format; 530 531 // Copybit region is the destRect 532 LayerRect region_rect; 533 region_rect.left = FLOAT(dst_rect.l); 534 region_rect.top = FLOAT(dst_rect.t); 535 region_rect.right = FLOAT(dst_rect.r); 536 region_rect.bottom = FLOAT(dst_rect.b); 537 538 LayerRectArray region; 539 region.count = 1; 540 region.rect = ®ion_rect; 541 RegionIterator copybitRegion(region); 542 int acquireFd = layer_buffer.acquire_fence_fd; 543 544 // FRAMEBUFFER_WIDTH/HEIGHT for c2d is the target buffer w/h 545 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_FRAMEBUFFER_WIDTH, 546 target_buffer->width); 547 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_FRAMEBUFFER_HEIGHT, 548 target_buffer->height); 549 int transform = 0; 550 if (layer->transform.rotation != 0.0f) transform |= COPYBIT_TRANSFORM_ROT_90; 551 if (layer->transform.flip_horizontal) transform |= COPYBIT_TRANSFORM_FLIP_H; 552 if (layer->transform.flip_vertical) transform |= COPYBIT_TRANSFORM_FLIP_V; 553 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_TRANSFORM, transform); 554 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_PLANE_ALPHA, hwc_layer->planeAlpha); 555 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_BLEND_MODE, hwc_layer->blending); 556 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_DITHER, 557 (dst.format == HAL_PIXEL_FORMAT_RGB_565) ? COPYBIT_ENABLE : COPYBIT_DISABLE); 558 559 int src_format_mode = COPYBIT_LINEAR; 560 if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) { 561 src_format_mode = COPYBIT_UBWC_COMPRESSED; 562 } 563 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_SRC_FORMAT_MODE, src_format_mode); 564 565 blit_engine_c2d_->set_sync(blit_engine_c2d_, acquireFd); 566 int err = blit_engine_c2d_->stretch(blit_engine_c2d_, &dst, &src, &dst_rect, &src_rect, 567 ©bitRegion); 568 569 if (err < 0) { 570 DLOGE("copybit stretch failed"); 571 } 572 573 return err; 574 } 575 576 void BlitEngineC2d::DumpBlitTargetBuffer(int fd) { 577 if (!dump_frame_count_) { 578 return; 579 } 580 581 private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_]; 582 583 if (fd >= 0) { 584 int error = sync_wait(fd, 1000); 585 if (error < 0) { 586 DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno)); 587 return; 588 } 589 } 590 591 char dump_file_name[PATH_MAX]; 592 size_t result = 0; 593 snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary" 594 "/blit_target_%d.raw", (dump_frame_index_)); 595 FILE* fp = fopen(dump_file_name, "w+"); 596 if (fp) { 597 result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp); 598 fclose(fp); 599 } 600 dump_frame_count_--; 601 dump_frame_index_++; 602 } 603 604 } // namespace sdm 605 #if defined(__clang__) 606 #pragma clang diagnostic pop 607 #endif 608 609