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.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 
PreCommit(hwc_display_contents_1_t * content_list,LayerStack * layer_stack)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 
Commit(hwc_display_contents_1_t * content_list,LayerStack * layer_stack)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 
DrawRectUsingCopybit(hwc_layer_1_t * hwc_layer,Layer * layer,LayerRect blit_rect,LayerRect blit_dest_Rect)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  = &region_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                                       &copybitRegion);
568 
569   if (err < 0) {
570     DLOGE("copybit stretch failed");
571   }
572 
573   return err;
574 }
575 
DumpBlitTargetBuffer(int fd)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