• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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->GetMixerResolution(&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, NULL,
100                DISPLAY_CLASS_VIRTUAL) {
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     output_buffer_ = NULL;
123   }
124 
125   return status;
126 }
127 
Prepare(hwc_display_contents_1_t * content_list)128 int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
129   int status = 0;
130 
131   status = SetOutputSliceFromMetadata(content_list);
132   if (status) {
133     return status;
134   }
135 
136   if (display_paused_) {
137     MarkLayersForGPUBypass(content_list);
138     return status;
139   }
140 
141   status = AllocateLayerStack(content_list);
142   if (status) {
143     return status;
144   }
145 
146   status = SetOutputBuffer(content_list);
147   if (status) {
148     return status;
149   }
150 
151   status = PrePrepareLayerStack(content_list);
152   if (status) {
153     return status;
154   }
155 
156   status = PrepareLayerStack(content_list);
157   if (status) {
158     return status;
159   }
160 
161   return 0;
162 }
163 
Commit(hwc_display_contents_1_t * content_list)164 int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
165   int status = 0;
166   if (display_paused_) {
167     DisplayError error = display_intf_->Flush();
168     if (error != kErrorNone) {
169       DLOGE("Flush failed. Error = %d", error);
170     }
171     return status;
172   }
173 
174   CommitOutputBufferParams(content_list);
175 
176   status = HWCDisplay::CommitLayerStack(content_list);
177   if (status) {
178     return status;
179   }
180 
181   if (dump_frame_count_ && !flush_ && dump_output_layer_) {
182     const private_handle_t *output_handle = (const private_handle_t *)(content_list->outbuf);
183     if (output_handle && output_handle->base) {
184       BufferInfo buffer_info;
185       buffer_info.buffer_config.width = static_cast<uint32_t>(output_handle->width);
186       buffer_info.buffer_config.height = static_cast<uint32_t>(output_handle->height);
187       buffer_info.buffer_config.format = GetSDMFormat(output_handle->format, output_handle->flags);
188       buffer_info.alloc_buffer_info.size = static_cast<uint32_t>(output_handle->size);
189       DumpOutputBuffer(buffer_info, reinterpret_cast<void *>(output_handle->base),
190                        layer_stack_.retire_fence_fd);
191     }
192   }
193 
194   status = HWCDisplay::PostCommitLayerStack(content_list);
195   if (status) {
196     return status;
197   }
198 
199   return 0;
200 }
201 
SetOutputSliceFromMetadata(hwc_display_contents_1_t * content_list)202 int HWCDisplayVirtual::SetOutputSliceFromMetadata(hwc_display_contents_1_t *content_list) {
203   const private_handle_t *output_handle =
204         static_cast<const private_handle_t *>(content_list->outbuf);
205   DisplayError error = kErrorNone;
206   int status = 0;
207 
208   if (output_handle) {
209     int output_handle_format = output_handle->format;
210     if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
211       output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
212     }
213 
214     LayerBufferFormat format = GetSDMFormat(output_handle_format, output_handle->flags);
215     if (format == kFormatInvalid) {
216       return -EINVAL;
217     }
218 
219     int active_width;
220     int active_height;
221 
222     AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, active_width,
223                                                           active_height);
224 
225     if ((active_width != INT(output_buffer_->width)) ||
226         (active_height!= INT(output_buffer_->height)) ||
227         (format != output_buffer_->format)) {
228       // Populate virtual display attributes based on displayFrame of FBT.
229       // For DRC, use width and height populated in metadata (unaligned values)
230       // for setting attributes of virtual display. This is needed because if
231       // we use aligned width and height, scaling will be required for FBT layer.
232       DisplayConfigVariableInfo variable_info;
233       hwc_layer_1_t &fbt_layer = content_list->hwLayers[content_list->numHwLayers-1];
234       hwc_rect_t &frame = fbt_layer.displayFrame;
235       int fbt_width = frame.right - frame.left;
236       int fbt_height = frame.bottom - frame.top;
237       const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(output_handle->base_metadata);
238       if (meta_data && meta_data->operation & UPDATE_BUFFER_GEOMETRY) {
239         variable_info.x_pixels = UINT32(meta_data->bufferDim.sliceWidth);
240         variable_info.y_pixels = UINT32(meta_data->bufferDim.sliceHeight);
241       } else {
242         variable_info.x_pixels = UINT32(fbt_width);
243         variable_info.y_pixels = UINT32(fbt_height);
244       }
245       // TODO(user): Need to get the framerate of primary display and update it.
246       variable_info.fps = 60;
247 
248       error = display_intf_->SetActiveConfig(&variable_info);
249       if (error != kErrorNone) {
250         return -EINVAL;
251       }
252 
253       status = SetOutputBuffer(content_list);
254       if (status) {
255         return status;
256       }
257     }
258   }
259 
260   return 0;
261 }
262 
SetOutputBuffer(hwc_display_contents_1_t * content_list)263 int HWCDisplayVirtual::SetOutputBuffer(hwc_display_contents_1_t *content_list) {
264   const private_handle_t *output_handle =
265         static_cast<const private_handle_t *>(content_list->outbuf);
266 
267   if (output_handle) {
268     int output_handle_format = output_handle->format;
269 
270     if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
271       output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
272     }
273 
274     output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
275 
276     if (output_buffer_->format == kFormatInvalid) {
277       return -EINVAL;
278     }
279 
280     int output_buffer_width, output_buffer_height;
281     AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, output_buffer_width,
282                                                           output_buffer_height);
283 
284     output_buffer_->width = UINT32(output_buffer_width);
285     output_buffer_->height = UINT32(output_buffer_height);
286     output_buffer_->flags.secure = 0;
287     output_buffer_->flags.video = 0;
288 
289     // TZ Protected Buffer - L1
290     if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
291       output_buffer_->flags.secure = 1;
292     }
293   }
294 
295   layer_stack_.output_buffer = output_buffer_;
296 
297   return 0;
298 }
299 
CommitOutputBufferParams(hwc_display_contents_1_t * content_list)300 void HWCDisplayVirtual::CommitOutputBufferParams(hwc_display_contents_1_t *content_list) {
301   const private_handle_t *output_handle =
302         static_cast<const private_handle_t *>(content_list->outbuf);
303 
304   // Fill output buffer parameters (width, height, format, plane information, fence)
305   output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
306 
307   if (output_handle) {
308     // ToDo: Need to extend for non-RGB formats
309     output_buffer_->planes[0].fd = output_handle->fd;
310     output_buffer_->planes[0].offset = output_handle->offset;
311     output_buffer_->planes[0].stride = UINT32(output_handle->width);
312   }
313 }
314 
SetFrameDumpConfig(uint32_t count,uint32_t bit_mask_layer_type)315 void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
316   HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
317   dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
318 
319   DLOGI("output_layer_dump_enable %d", dump_output_layer_);
320 }
321 
322 }  // namespace sdm
323 
324