1 /*
2 * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *     * Redistributions of source code must retain the above copyright
8 *       notice, this list of conditions and the following disclaimer.
9 *     * Redistributions in binary form must reproduce the above
10 *       copyright notice, this list of conditions and the following
11 *       disclaimer in the documentation and/or other materials provided
12 *       with the distribution.
13 *     * Neither the name of The Linux Foundation nor the names of its
14 *       contributors may be used to endorse or promote products derived
15 *       from this software without specific prior written permission.
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 
30 #include <utils/constants.h>
31 #include <utils/debug.h>
32 #include <sync/sync.h>
33 #include <stdarg.h>
34 #include <gr.h>
35 
36 #include "hwc_display_virtual.h"
37 #include "hwc_debugger.h"
38 
39 #define __CLASS__ "HWCDisplayVirtual"
40 
41 namespace sdm {
42 
Create(CoreInterface * core_intf,hwc_procs_t const ** hwc_procs,uint32_t primary_width,uint32_t primary_height,hwc_display_contents_1_t * content_list,HWCDisplay ** hwc_display)43 int HWCDisplayVirtual::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
44                               uint32_t primary_width, uint32_t primary_height,
45                               hwc_display_contents_1_t *content_list,
46                               HWCDisplay **hwc_display) {
47   int status = 0;
48   HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, hwc_procs);
49   uint32_t virtual_width = 0, virtual_height = 0;
50 
51   status = hwc_display_virtual->Init();
52   if (status) {
53     delete hwc_display_virtual;
54     return status;
55   }
56 
57   status = hwc_display_virtual->SetPowerMode(HWC_POWER_MODE_NORMAL);
58   if (status) {
59     Destroy(hwc_display_virtual);
60     return status;
61   }
62 
63   // TODO(user): Need to update resolution(and not aligned resolution) on writeback.
64   status = hwc_display_virtual->SetOutputSliceFromMetadata(content_list);
65   if (status) {
66     Destroy(hwc_display_virtual);
67     return status;
68   }
69 
70   hwc_display_virtual->GetPanelResolution(&virtual_width, &virtual_height);
71 
72   if (content_list->numHwLayers < 1) {
73     Destroy(hwc_display_virtual);
74     return -1;
75   }
76 
77   hwc_layer_1_t &fb_layer = content_list->hwLayers[content_list->numHwLayers-1];
78   int fb_width = fb_layer.displayFrame.right - fb_layer.displayFrame.left;
79   int fb_height = fb_layer.displayFrame.bottom - fb_layer.displayFrame.top;
80 
81   status = hwc_display_virtual->SetFrameBufferResolution(UINT32(fb_width), UINT32(fb_height));
82 
83   if (status) {
84     Destroy(hwc_display_virtual);
85     return status;
86   }
87 
88   *hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
89 
90   return 0;
91 }
92 
Destroy(HWCDisplay * hwc_display)93 void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
94   hwc_display->Deinit();
95   delete hwc_display;
96 }
97 
HWCDisplayVirtual(CoreInterface * core_intf,hwc_procs_t const ** hwc_procs)98 HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
99   : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL, false),
100     dump_output_layer_(false), output_buffer_(NULL) {
101 }
102 
Init()103 int HWCDisplayVirtual::Init() {
104   output_buffer_ = new LayerBuffer();
105   if (!output_buffer_) {
106     return -ENOMEM;
107   }
108 
109   return HWCDisplay::Init();
110 }
111 
Deinit()112 int HWCDisplayVirtual::Deinit() {
113   int status = 0;
114 
115   status = HWCDisplay::Deinit();
116   if (status) {
117     return status;
118   }
119 
120   if (output_buffer_) {
121     delete output_buffer_;
122   }
123 
124   return status;
125 }
126 
Prepare(hwc_display_contents_1_t * content_list)127 int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
128   int status = 0;
129 
130   status = SetOutputSliceFromMetadata(content_list);
131   if (status) {
132     return status;
133   }
134 
135   if (display_paused_) {
136     MarkLayersForGPUBypass(content_list);
137     return status;
138   }
139 
140   status = AllocateLayerStack(content_list);
141   if (status) {
142     return status;
143   }
144 
145   status = SetOutputBuffer(content_list);
146   if (status) {
147     return status;
148   }
149 
150   status = PrePrepareLayerStack(content_list);
151   if (status) {
152     return status;
153   }
154 
155   status = PrepareLayerStack(content_list);
156   if (status) {
157     return status;
158   }
159 
160   return 0;
161 }
162 
Commit(hwc_display_contents_1_t * content_list)163 int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
164   int status = 0;
165   if (display_paused_) {
166     DisplayError error = display_intf_->Flush();
167     if (error != kErrorNone) {
168       DLOGE("Flush failed. Error = %d", error);
169     }
170     return status;
171   }
172 
173   status = HWCDisplay::CommitLayerStack(content_list);
174   if (status) {
175     return status;
176   }
177 
178   DumpOutputBuffer(content_list);
179 
180   status = HWCDisplay::PostCommitLayerStack(content_list);
181   if (status) {
182     return status;
183   }
184 
185   return 0;
186 }
187 
SetOutputSliceFromMetadata(hwc_display_contents_1_t * content_list)188 int HWCDisplayVirtual::SetOutputSliceFromMetadata(hwc_display_contents_1_t *content_list) {
189   const private_handle_t *output_handle =
190         static_cast<const private_handle_t *>(content_list->outbuf);
191   DisplayError error = kErrorNone;
192   int status = 0;
193 
194   if (output_handle) {
195     int output_handle_format = output_handle->format;
196     if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
197       output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
198     }
199 
200     LayerBufferFormat format = GetSDMFormat(output_handle_format, output_handle->flags);
201     if (format == kFormatInvalid) {
202       return -EINVAL;
203     }
204 
205     int active_width;
206     int active_height;
207 
208     AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, active_width,
209                                                           active_height);
210 
211     if ((active_width != INT(output_buffer_->width)) ||
212         (active_height!= INT(output_buffer_->height)) ||
213         (format != output_buffer_->format)) {
214       // Populate virtual display attributes based on displayFrame of FBT.
215       // For DRC, use width and height populated in metadata (unaligned values)
216       // for setting attributes of virtual display. This is needed because if
217       // we use aligned width and height, scaling will be required for FBT layer.
218       DisplayConfigVariableInfo variable_info;
219       hwc_layer_1_t &fbt_layer = content_list->hwLayers[content_list->numHwLayers-1];
220       hwc_rect_t &frame = fbt_layer.displayFrame;
221       int fbt_width = frame.right - frame.left;
222       int fbt_height = frame.bottom - frame.top;
223       const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(output_handle->base_metadata);
224       if (meta_data && meta_data->operation & UPDATE_BUFFER_GEOMETRY) {
225         variable_info.x_pixels = UINT32(meta_data->bufferDim.sliceWidth);
226         variable_info.y_pixels = UINT32(meta_data->bufferDim.sliceHeight);
227       } else {
228         variable_info.x_pixels = UINT32(fbt_width);
229         variable_info.y_pixels = UINT32(fbt_height);
230       }
231       // TODO(user): Need to get the framerate of primary display and update it.
232       variable_info.fps = 60;
233 
234       error = display_intf_->SetActiveConfig(&variable_info);
235       if (error != kErrorNone) {
236         return -EINVAL;
237       }
238 
239       status = SetOutputBuffer(content_list);
240       if (status) {
241         return status;
242       }
243     }
244   }
245 
246   return 0;
247 }
248 
SetOutputBuffer(hwc_display_contents_1_t * content_list)249 int HWCDisplayVirtual::SetOutputBuffer(hwc_display_contents_1_t *content_list) {
250   int status = 0;
251 
252   const private_handle_t *output_handle =
253         static_cast<const private_handle_t *>(content_list->outbuf);
254 
255   // Fill output buffer parameters (width, height, format, plane information, fence)
256   output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
257 
258   if (output_handle) {
259     int output_handle_format = output_handle->format;
260 
261     if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
262       output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
263     }
264 
265     output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
266 
267     if (output_buffer_->format == kFormatInvalid) {
268       return -EINVAL;
269     }
270 
271     int output_buffer_width, output_buffer_height;
272     AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, output_buffer_width,
273                                                           output_buffer_height);
274 
275     output_buffer_->width = UINT32(output_buffer_width);
276     output_buffer_->height = UINT32(output_buffer_height);
277     output_buffer_->flags.secure = 0;
278     output_buffer_->flags.video = 0;
279 
280     // TZ Protected Buffer - L1
281     if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
282       output_buffer_->flags.secure = 1;
283     }
284 
285     // ToDo: Need to extend for non-RGB formats
286     output_buffer_->planes[0].fd = output_handle->fd;
287     output_buffer_->planes[0].offset = output_handle->offset;
288     output_buffer_->planes[0].stride = UINT32(output_handle->width);
289   }
290 
291   layer_stack_.output_buffer = output_buffer_;
292 
293   return status;
294 }
295 
DumpOutputBuffer(hwc_display_contents_1_t * content_list)296 void HWCDisplayVirtual::DumpOutputBuffer(hwc_display_contents_1_t *content_list) {
297   const private_handle_t *output_handle = (const private_handle_t *)(content_list->outbuf);
298   char dir_path[PATH_MAX];
299 
300   if (!dump_frame_count_ || flush_ || !dump_output_layer_) {
301     return;
302   }
303 
304   snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
305 
306   if (mkdir(dir_path, 777) != 0 && errno != EEXIST) {
307     DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
308     return;
309   }
310 
311   // if directory exists already, need to explicitly change the permission.
312   if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
313     DLOGW("Failed to change permissions on %s directory", dir_path);
314     return;
315   }
316 
317   if (output_handle && output_handle->base) {
318     char dump_file_name[PATH_MAX];
319     size_t result = 0;
320 
321     if (content_list->outbufAcquireFenceFd >= 0) {
322       int error = sync_wait(content_list->outbufAcquireFenceFd, 1000);
323       if (error < 0) {
324         DLOGW("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
325         return;
326       }
327     }
328 
329     snprintf(dump_file_name, sizeof(dump_file_name), "%s/output_layer_%dx%d_%s_frame%d.raw",
330              dir_path, output_handle->width, output_handle->height,
331              GetHALPixelFormatString(output_handle->format), dump_frame_index_);
332 
333     FILE* fp = fopen(dump_file_name, "w+");
334     if (fp) {
335       result = fwrite(reinterpret_cast<void *>(output_handle->base), output_handle->size, 1, fp);
336       fclose(fp);
337     }
338 
339     DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
340   }
341 }
342 
SetFrameDumpConfig(uint32_t count,uint32_t bit_mask_layer_type)343 void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
344   HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
345   dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
346 
347   DLOGI("output_layer_dump_enable %d", dump_output_layer_);
348 }
349 
350 }  // namespace sdm
351 
352