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
RegionIterator(LayerRectArray rect)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
iterate(copybit_region_t const * self,copybit_rect_t * rect)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
BlitEngineC2d()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
~BlitEngineC2d()107 BlitEngineC2d::~BlitEngineC2d() {
108 if (blit_engine_c2d_) {
109 copybit_close(blit_engine_c2d_);
110 blit_engine_c2d_ = NULL;
111 }
112 FreeBlitTargetBuffers();
113 }
114
Init()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
DeInit()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
AllocateBlitTargetBuffers(uint32_t width,uint32_t height,uint32_t format,uint32_t usage)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
FreeBlitTargetBuffers()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
ClearTargetBuffer(private_handle_t * hnd,const LayerRect & rect)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
PostCommit(LayerStack * layer_stack)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
SetReleaseFence(int 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
BlitActive()245 bool BlitEngineC2d::BlitActive() {
246 return blit_active_;
247 }
248
SetFrameDumpConfig(uint32_t count)249 void BlitEngineC2d::SetFrameDumpConfig(uint32_t count) {
250 dump_frame_count_ = count;
251 dump_frame_index_ = 0;
252 }
253
Prepare(LayerStack * layer_stack)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->width);
286 int fbheight = INT(layer_buffer->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
298 // Set the buffer height and width
299 layer_buffer->width = fbwidth;
300 layer_buffer->height = fbheight/3;
301
302 layer->plane_alpha = 0xFF;
303 layer->blending = kBlendingOpaque;
304 layer->composition = kCompositionBlitTarget;
305 layer->frame_rate = layer_stack->layers.at(gpu_target_index)->frame_rate;
306 }
307
308 return 0;
309 }
310
PreCommit(hwc_display_contents_1_t * content_list,LayerStack * layer_stack)311 int BlitEngineC2d::PreCommit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) {
312 int status = 0;
313 uint32_t num_app_layers = (uint32_t) content_list->numHwLayers-1;
314 int target_width = 0;
315 int target_height = 0;
316 uint32_t processed_blit = 0;
317 LayerRect dst_rects[kMaxBlitTargetLayers];
318 bool blit_needed = false;
319 uint32_t usage = 0;
320
321 if (!num_app_layers) {
322 return -1;
323 }
324
325 for (uint32_t i = num_app_layers-1; (i > 0) && (processed_blit < num_blit_target_); i--) {
326 Layer *layer = layer_stack->layers.at(i);
327 if (layer->composition != kCompositionBlit) {
328 continue;
329 }
330 blit_needed = true;
331 layer_stack->flags.attributes_changed = true;
332
333 Layer *blit_layer = layer_stack->layers.at(blit_target_start_index_ + processed_blit);
334 LayerRect &blit_src_rect = blit_layer->src_rect;
335 int width = INT(layer->dst_rect.right - layer->dst_rect.left);
336 int height = INT(layer->dst_rect.bottom - layer->dst_rect.top);
337 usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_HW_TEXTURE;
338 if (blit_engine_c2d_->get(blit_engine_c2d_, COPYBIT_UBWC_SUPPORT) > 0) {
339 usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
340 }
341 // TODO(user): FrameBuffer is assumed to be RGBA
342 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width, height,
343 INT(HAL_PIXEL_FORMAT_RGBA_8888), usage, width, height);
344
345 target_width = std::max(target_width, width);
346 target_height += height;
347
348 // Left will be zero always
349 dst_rects[processed_blit].top = FLOAT(target_height - height);
350 dst_rects[processed_blit].right = dst_rects[processed_blit].left +
351 (layer->dst_rect.right - layer->dst_rect.left);
352 dst_rects[processed_blit].bottom = (dst_rects[processed_blit].top +
353 (layer->dst_rect.bottom - layer->dst_rect.top));
354 blit_src_rect = dst_rects[processed_blit];
355 processed_blit++;
356 }
357
358 // Allocate a single buffer of RGBA8888 format
359 if (blit_needed && (AllocateBlitTargetBuffers(target_width, target_height,
360 HAL_PIXEL_FORMAT_RGBA_8888, usage) < 0)) {
361 status = -1;
362 return status;
363 }
364
365 if (blit_needed) {
366 for (uint32_t j = 0; j < num_blit_target_; j++) {
367 Layer *layer = layer_stack->layers.at(j + content_list->numHwLayers);
368 private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
369 // Set the fd information
370 layer->input_buffer->width = target_width;
371 layer->input_buffer->height = target_height;
372 if (target_buffer->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
373 layer->input_buffer->format = kFormatRGBA8888Ubwc;
374 }
375 layer->input_buffer->planes[0].fd = target_buffer->fd;
376 layer->input_buffer->planes[0].offset = 0;
377 layer->input_buffer->planes[0].stride = target_buffer->width;
378 }
379 }
380
381 return status;
382 }
383
Commit(hwc_display_contents_1_t * content_list,LayerStack * layer_stack)384 int BlitEngineC2d::Commit(hwc_display_contents_1_t *content_list, LayerStack *layer_stack) {
385 int fd = -1;
386 int status = 0;
387 bool hybrid_present = false;
388 uint32_t num_app_layers = (uint32_t) content_list->numHwLayers-1;
389 private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
390 blit_active_ = false;
391
392 if (!num_app_layers) {
393 return -1;
394 }
395
396 // if not Blit Targets return
397 for (uint32_t i = 0; i < num_app_layers; i++) {
398 Layer *layer = layer_stack->layers.at(i);
399 if (layer->composition == kCompositionHybrid || layer->composition == kCompositionBlit) {
400 hybrid_present = true;
401 }
402 }
403
404 if (!hybrid_present) {
405 return status;
406 }
407
408 // Clear blit target buffer
409 LayerRect clear_rect;
410 clear_rect.left = 0;
411 clear_rect.top = 0;
412 clear_rect.right = FLOAT(target_buffer->width);
413 clear_rect.bottom = FLOAT(target_buffer->height);
414 ClearTargetBuffer(target_buffer, clear_rect);
415
416 int copybit_layer_count = 0;
417 uint32_t processed_blit = 0;
418 for (uint32_t i = num_app_layers-1; (i > 0) && (processed_blit < num_blit_target_) &&
419 (status == 0); i--) {
420 Layer *layer = layer_stack->layers.at(i);
421 if (layer->composition != kCompositionBlit) {
422 continue;
423 }
424
425 for (uint32_t k = 0; k <= i; k++) {
426 Layer *bottom_layer = layer_stack->layers.at(k);
427 LayerBuffer *layer_buffer = bottom_layer->input_buffer;
428 // if layer below the blit layer does not intersect, ignore that layer
429 LayerRect inter_sect = Intersection(layer->dst_rect, bottom_layer->dst_rect);
430 if (bottom_layer->composition != kCompositionHybrid && !IsValid(inter_sect)) {
431 continue;
432 }
433 if (bottom_layer->composition == kCompositionGPU ||
434 bottom_layer->composition == kCompositionSDE ||
435 bottom_layer->composition == kCompositionGPUTarget) {
436 continue;
437 }
438
439 // For each layer marked as Hybrid, wait for acquire fence and then blit using the C2D
440 if (layer_buffer->acquire_fence_fd >= 0) {
441 // Wait for acquire fence on the App buffers.
442 if (sync_wait(layer_buffer->acquire_fence_fd, 1000) < 0) {
443 DLOGE("sync_wait error!! error no = %d err str = %s", errno, strerror(errno));
444 }
445 layer_buffer->acquire_fence_fd = -1;
446 }
447 hwc_layer_1_t *hwc_layer = &content_list->hwLayers[k];
448 LayerRect &src_rect = bottom_layer->blit_regions.at(processed_blit);
449 Layer *blit_layer = layer_stack->layers.at(blit_target_start_index_ + processed_blit);
450 LayerRect dest_rect = blit_layer->src_rect;
451 int ret_val = DrawRectUsingCopybit(hwc_layer, bottom_layer, src_rect, dest_rect);
452 copybit_layer_count++;
453 if (ret_val < 0) {
454 copybit_layer_count = 0;
455 DLOGE("DrawRectUsingCopyBit failed");
456 status = -1;
457 break;
458 }
459 }
460 processed_blit++;
461 }
462
463 if (copybit_layer_count) {
464 blit_active_ = true;
465 blit_engine_c2d_->flush_get_fence(blit_engine_c2d_, &fd);
466 }
467
468 if (blit_active_) {
469 // dump the render buffer
470 DumpBlitTargetBuffer(fd);
471
472 // Set the fd to the LayerStack BlitTargets fd
473 uint32_t layer_count = UINT32(layer_stack->layers.size());
474 for (uint32_t k = blit_target_start_index_; k < layer_count; k++) {
475 Layer *layer = layer_stack->layers.at(k);
476 LayerBuffer *layer_buffer = layer->input_buffer;
477 layer_buffer->acquire_fence_fd = fd;
478 }
479 }
480
481 return status;
482 }
483
DrawRectUsingCopybit(hwc_layer_1_t * hwc_layer,Layer * layer,LayerRect blit_rect,LayerRect blit_dest_Rect)484 int BlitEngineC2d::DrawRectUsingCopybit(hwc_layer_1_t *hwc_layer, Layer *layer,
485 LayerRect blit_rect, LayerRect blit_dest_Rect) {
486 private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
487 const private_handle_t *hnd = static_cast<const private_handle_t *>(hwc_layer->handle);
488 LayerBuffer *layer_buffer = layer->input_buffer;
489
490 // Set the Copybit Source
491 copybit_image_t src;
492 src.handle = const_cast<native_handle_t *>(hwc_layer->handle);
493 src.w = hnd->width;
494 src.h = hnd->height;
495 src.base = reinterpret_cast<void *>(hnd->base);
496 src.format = hnd->format;
497 src.horiz_padding = 0;
498 src.vert_padding = 0;
499
500 // Copybit source rect
501 copybit_rect_t src_rect = {INT(blit_rect.left), INT(blit_rect.top), INT(blit_rect.right),
502 INT(blit_rect.bottom)};
503
504 // Copybit destination rect
505 copybit_rect_t dst_rect = {INT(blit_dest_Rect.left), INT(blit_dest_Rect.top),
506 INT(blit_dest_Rect.right), INT(blit_dest_Rect.bottom)};
507
508 // Copybit destination buffer
509 copybit_image_t dst;
510 dst.handle = static_cast<native_handle_t *>(target_buffer);
511 dst.w = ALIGN(target_buffer->width, 32);
512 dst.h = ALIGN((target_buffer->height), 32);
513 dst.base = reinterpret_cast<void *>(target_buffer->base);
514 dst.format = target_buffer->format;
515
516 // Copybit region is the destRect
517 LayerRect region_rect;
518 region_rect.left = FLOAT(dst_rect.l);
519 region_rect.top = FLOAT(dst_rect.t);
520 region_rect.right = FLOAT(dst_rect.r);
521 region_rect.bottom = FLOAT(dst_rect.b);
522
523 LayerRectArray region;
524 region.count = 1;
525 region.rect = ®ion_rect;
526 RegionIterator copybitRegion(region);
527 int acquireFd = layer_buffer->acquire_fence_fd;
528
529 // FRAMEBUFFER_WIDTH/HEIGHT for c2d is the target buffer w/h
530 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_FRAMEBUFFER_WIDTH,
531 target_buffer->width);
532 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_FRAMEBUFFER_HEIGHT,
533 target_buffer->height);
534 int transform = 0;
535 if (layer->transform.rotation != 0.0f) transform |= COPYBIT_TRANSFORM_ROT_90;
536 if (layer->transform.flip_horizontal) transform |= COPYBIT_TRANSFORM_FLIP_H;
537 if (layer->transform.flip_vertical) transform |= COPYBIT_TRANSFORM_FLIP_V;
538 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_TRANSFORM, transform);
539 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_PLANE_ALPHA, hwc_layer->planeAlpha);
540 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_BLEND_MODE, hwc_layer->blending);
541 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_DITHER,
542 (dst.format == HAL_PIXEL_FORMAT_RGB_565) ? COPYBIT_ENABLE : COPYBIT_DISABLE);
543
544 int src_format_mode = COPYBIT_LINEAR;
545 if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
546 src_format_mode = COPYBIT_UBWC_COMPRESSED;
547 }
548 blit_engine_c2d_->set_parameter(blit_engine_c2d_, COPYBIT_SRC_FORMAT_MODE, src_format_mode);
549
550 blit_engine_c2d_->set_sync(blit_engine_c2d_, acquireFd);
551 int err = blit_engine_c2d_->stretch(blit_engine_c2d_, &dst, &src, &dst_rect, &src_rect,
552 ©bitRegion);
553
554 if (err < 0) {
555 DLOGE("copybit stretch failed");
556 }
557
558 return err;
559 }
560
DumpBlitTargetBuffer(int fd)561 void BlitEngineC2d::DumpBlitTargetBuffer(int fd) {
562 if (!dump_frame_count_) {
563 return;
564 }
565
566 private_handle_t *target_buffer = blit_target_buffer_[current_blit_target_index_];
567
568 if (fd >= 0) {
569 int error = sync_wait(fd, 1000);
570 if (error < 0) {
571 DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
572 return;
573 }
574 }
575
576 char dump_file_name[PATH_MAX];
577 size_t result = 0;
578 snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary"
579 "/blit_target_%d.raw", (dump_frame_index_));
580 FILE* fp = fopen(dump_file_name, "w+");
581 if (fp) {
582 result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp);
583 fclose(fp);
584 }
585 dump_frame_count_--;
586 dump_frame_index_++;
587 }
588
589 } // namespace sdm
590 #if defined(__clang__)
591 #pragma clang diagnostic pop
592 #endif
593
594