1/*
2* Copyright (c) 2014-2017, 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#ifndef USE_GRALLOC1
35#include <gr.h>
36#endif
37
38#include "hwc_display_virtual.h"
39#include "hwc_debugger.h"
40
41#define __CLASS__ "HWCDisplayVirtual"
42
43namespace sdm {
44
45int HWCDisplayVirtual::Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
46                              HWCCallbacks *callbacks, uint32_t width,
47                              uint32_t height, int32_t *format, HWCDisplay **hwc_display) {
48  int status = 0;
49  HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, buffer_allocator,
50                                                                 callbacks);
51
52  // TODO(user): Populate format correctly
53  DLOGI("Creating virtual display: w: %d h:%d format:0x%x", width, height, *format);
54
55  status = hwc_display_virtual->Init();
56  if (status) {
57    DLOGW("Failed to initialize virtual display");
58    delete hwc_display_virtual;
59    return status;
60  }
61
62  status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On));
63  if (status) {
64    DLOGW("Failed to set power mode on virtual display");
65    Destroy(hwc_display_virtual);
66    return status;
67  }
68
69  status = hwc_display_virtual->SetConfig(width, height);
70  if (status) {
71    Destroy(hwc_display_virtual);
72    return status;
73  }
74
75  // TODO(user): Validate that we support this width/height
76  status = hwc_display_virtual->SetFrameBufferResolution(width, height);
77
78  if (status) {
79    DLOGW("Failed to set virtual display FB resolution");
80    Destroy(hwc_display_virtual);
81    return status;
82  }
83
84  *hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
85
86  return 0;
87}
88
89void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
90  hwc_display->Deinit();
91  delete hwc_display;
92}
93
94HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
95                                     HWCCallbacks *callbacks)
96    : HWCDisplay(core_intf, callbacks, kVirtual, HWC_DISPLAY_VIRTUAL, false, NULL,
97                 DISPLAY_CLASS_VIRTUAL, buffer_allocator) {
98}
99
100int HWCDisplayVirtual::Init() {
101  output_buffer_ = new LayerBuffer();
102  return HWCDisplay::Init();
103}
104
105int HWCDisplayVirtual::Deinit() {
106  int status = 0;
107  if (output_buffer_) {
108    delete output_buffer_;
109    output_buffer_ = nullptr;
110  }
111  status = HWCDisplay::Deinit();
112
113  return status;
114}
115
116HWC2::Error HWCDisplayVirtual::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
117  auto status = HWC2::Error::None;
118
119  if (display_paused_) {
120    MarkLayersForGPUBypass();
121    return status;
122  }
123
124  BuildLayerStack();
125  layer_stack_.output_buffer = output_buffer_;
126  status = PrepareLayerStack(out_num_types, out_num_requests);
127  return status;
128}
129
130HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
131  auto status = HWC2::Error::None;
132  if (display_paused_) {
133    DisplayError error = display_intf_->Flush();
134    if (error != kErrorNone) {
135      DLOGE("Flush failed. Error = %d", error);
136    }
137  } else {
138    status = HWCDisplay::CommitLayerStack();
139    if (status == HWC2::Error::None) {
140      if (dump_frame_count_ && !flush_ && dump_output_layer_) {
141        if (output_handle_ && output_handle_->base) {
142          BufferInfo buffer_info;
143          const private_handle_t *output_handle =
144              reinterpret_cast<const private_handle_t *>(output_buffer_->buffer_id);
145          buffer_info.buffer_config.width = static_cast<uint32_t>(output_handle->width);
146          buffer_info.buffer_config.height = static_cast<uint32_t>(output_handle->height);
147          buffer_info.buffer_config.format =
148              GetSDMFormat(output_handle->format, output_handle->flags);
149          buffer_info.alloc_buffer_info.size = static_cast<uint32_t>(output_handle->size);
150          DumpOutputBuffer(buffer_info, reinterpret_cast<void *>(output_handle->base),
151                           layer_stack_.retire_fence_fd);
152        }
153      }
154
155      status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
156    }
157  }
158  CloseAcquireFds();
159  close(output_buffer_->acquire_fence_fd);
160  return status;
161}
162
163int HWCDisplayVirtual::SetConfig(uint32_t width, uint32_t height) {
164  DisplayConfigVariableInfo variable_info;
165  variable_info.x_pixels = width;
166  variable_info.y_pixels = height;
167  // TODO(user): Need to get the framerate of primary display and update it.
168  variable_info.fps = 60;
169  return display_intf_->SetActiveConfig(&variable_info);
170}
171
172HWC2::Error HWCDisplayVirtual::SetOutputBuffer(buffer_handle_t buf, int32_t release_fence) {
173  if (buf == nullptr || release_fence == 0) {
174    return HWC2::Error::BadParameter;
175  }
176  const private_handle_t *output_handle = static_cast<const private_handle_t *>(buf);
177
178  // Fill output buffer parameters (width, height, format, plane information, fence)
179  output_buffer_->acquire_fence_fd = dup(release_fence);
180
181  if (output_handle) {
182    output_buffer_->buffer_id = reinterpret_cast<uint64_t>(output_handle);
183    int output_handle_format = output_handle->format;
184
185    if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
186      output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
187    }
188
189    output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
190
191    if (output_buffer_->format == kFormatInvalid) {
192      return HWC2::Error::BadParameter;
193    }
194
195    int aligned_width, aligned_height;
196#ifdef USE_GRALLOC1
197    buffer_allocator_->GetCustomWidthAndHeight(output_handle, &aligned_width, &aligned_height);
198#else
199    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, aligned_width,
200                                                          aligned_height);
201#endif
202
203    output_buffer_->width = UINT32(aligned_width);
204    output_buffer_->height = UINT32(aligned_height);
205    output_buffer_->flags.secure = 0;
206    output_buffer_->flags.video = 0;
207
208    // TZ Protected Buffer - L1
209    if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
210      output_buffer_->flags.secure = 1;
211    }
212
213    // ToDo: Need to extend for non-RGB formats
214    output_buffer_->planes[0].fd = output_handle->fd;
215    output_buffer_->planes[0].offset = output_handle->offset;
216    output_buffer_->planes[0].stride = UINT32(output_handle->width);
217  }
218
219  return HWC2::Error::None;
220}
221
222void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
223  HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
224  dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
225
226  DLOGI("output_layer_dump_enable %d", dump_output_layer_);
227}
228
229}  // namespace sdm
230