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
41namespace sdm {
42
43int 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
93void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
94  hwc_display->Deinit();
95  delete hwc_display;
96}
97
98HWCDisplayVirtual::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
103int HWCDisplayVirtual::Init() {
104  output_buffer_ = new LayerBuffer();
105  if (!output_buffer_) {
106    return -ENOMEM;
107  }
108
109  return HWCDisplay::Init();
110}
111
112int 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
128int 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
164int 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
202int 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
263int 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 aligned_width, aligned_height;
281    int unaligned_width, unaligned_height;
282
283    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, aligned_width,
284                                                          aligned_height);
285    AdrenoMemInfo::getInstance().getUnalignedWidthAndHeight(output_handle, unaligned_width,
286                                                            unaligned_height);
287
288    output_buffer_->width = UINT32(aligned_width);
289    output_buffer_->height = UINT32(aligned_height);
290    output_buffer_->unaligned_width = UINT32(unaligned_width);
291    output_buffer_->unaligned_height = UINT32(unaligned_height);
292    output_buffer_->flags.secure = 0;
293    output_buffer_->flags.video = 0;
294
295    const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(output_handle->base_metadata);
296    if (meta_data && SetCSC(meta_data, &output_buffer_->color_metadata) != kErrorNone) {
297      return kErrorNotSupported;
298    }
299
300    // TZ Protected Buffer - L1
301    if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
302      output_buffer_->flags.secure = 1;
303    }
304  }
305
306  layer_stack_.output_buffer = output_buffer_;
307
308  return 0;
309}
310
311void HWCDisplayVirtual::CommitOutputBufferParams(hwc_display_contents_1_t *content_list) {
312  const private_handle_t *output_handle =
313        static_cast<const private_handle_t *>(content_list->outbuf);
314
315  // Fill output buffer parameters (width, height, format, plane information, fence)
316  output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
317
318  if (output_handle) {
319    // ToDo: Need to extend for non-RGB formats
320    output_buffer_->planes[0].fd = output_handle->fd;
321    output_buffer_->planes[0].offset = output_handle->offset;
322    output_buffer_->planes[0].stride = UINT32(output_handle->width);
323  }
324}
325
326void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
327  HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
328  dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
329
330  DLOGI("output_layer_dump_enable %d", dump_output_layer_);
331}
332
333}  // namespace sdm
334
335