1 /*
2 * Copyright (c) 2019-2020, 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 <hwc_display_virtual_dpu.h>
31
32 #define __CLASS__ "HWCDisplayVirtualDPU"
33
34 namespace sdm {
35
HWCDisplayVirtualDPU(CoreInterface * core_intf,HWCBufferAllocator * buffer_allocator,HWCCallbacks * callbacks,hwc2_display_t id,int32_t sdm_id,uint32_t width,uint32_t height,float min_lum,float max_lum)36 HWCDisplayVirtualDPU::HWCDisplayVirtualDPU(CoreInterface *core_intf, HWCBufferAllocator
37 *buffer_allocator, HWCCallbacks *callbacks,
38 hwc2_display_t id, int32_t sdm_id, uint32_t width,
39 uint32_t height, float min_lum, float max_lum)
40 : HWCDisplayVirtual(core_intf, buffer_allocator, callbacks, id, sdm_id, width, height),
41 min_lum_(min_lum), max_lum_(max_lum) {
42 }
43
Init()44 int HWCDisplayVirtualDPU::Init() {
45 int status = HWCDisplay::Init();
46 if (status) {
47 DLOGE("Init failed: %d", status);
48 return status;
49 }
50
51 if (max_lum_ != -1.0 || min_lum_ != -1.0) {
52 SetPanelLuminanceAttributes(min_lum_, max_lum_);
53 }
54
55 status = SetConfig(width_, height_);
56 if (status) {
57 DLOGE("Failed to set width: %d height: %d", width_, height_);
58 return status;
59 }
60
61 status = INT32(SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
62 if (status) {
63 DLOGW("Failed to set power mode on virtual display");
64 return status;
65 }
66
67 // TODO(user): Validate that we support this width/height
68 status = SetFrameBufferResolution(width_, height_);
69 if (status) {
70 DLOGW("Failed to set FrameBuffer resolution on virtual display");
71 return status;
72 }
73
74 return HWCDisplayVirtual::Init();
75 }
76
SetConfig(uint32_t width,uint32_t height)77 int HWCDisplayVirtualDPU::SetConfig(uint32_t width, uint32_t height) {
78 DisplayConfigVariableInfo variable_info;
79 variable_info.x_pixels = width;
80 variable_info.y_pixels = height;
81 // TODO(user): Need to get the framerate of primary display and update it.
82 variable_info.fps = 60;
83
84 DisplayError err = display_intf_->SetActiveConfig(&variable_info);
85 if (err != kErrorNone) {
86 return -EINVAL;
87 }
88 return 0;
89 }
90
SetOutputBuffer(buffer_handle_t buf,shared_ptr<Fence> release_fence)91 HWC2::Error HWCDisplayVirtualDPU::SetOutputBuffer(buffer_handle_t buf,
92 shared_ptr<Fence> release_fence) {
93 HWC2::Error error = HWCDisplayVirtual::SetOutputBuffer(buf, release_fence);
94 if (error != HWC2::Error::None) {
95 return error;
96 }
97
98 const private_handle_t *output_handle = static_cast<const private_handle_t *>(buf);
99 if (output_handle) {
100 int output_handle_format = output_handle->format;
101 int active_aligned_w, active_aligned_h;
102 int new_width, new_height;
103 int new_aligned_w, new_aligned_h;
104 uint32_t active_width, active_height;
105
106 GetMixerResolution(&active_width, &active_height);
107 buffer_allocator_->GetCustomWidthAndHeight(output_handle, &new_width, &new_height);
108 buffer_allocator_->GetAlignedWidthAndHeight(INT(new_width), INT(new_height),
109 output_handle_format, 0, &new_aligned_w,
110 &new_aligned_h);
111 buffer_allocator_->GetAlignedWidthAndHeight(INT(active_width), INT(active_height),
112 output_handle_format, 0, &active_aligned_w,
113 &active_aligned_h);
114 if (new_aligned_w != active_aligned_w || new_aligned_h != active_aligned_h) {
115 int status = SetConfig(UINT32(new_width), UINT32(new_height));
116 if (status) {
117 DLOGE("SetConfig failed custom WxH %dx%d", new_width, new_height);
118 return HWC2::Error::BadParameter;
119 }
120 validated_ = false;
121 }
122
123 output_buffer_.width = UINT32(new_aligned_w);
124 output_buffer_.height = UINT32(new_aligned_h);
125 output_buffer_.unaligned_width = UINT32(new_width);
126 output_buffer_.unaligned_height = UINT32(new_height);
127 }
128
129 return HWC2::Error::None;
130 }
131
Validate(uint32_t * out_num_types,uint32_t * out_num_requests)132 HWC2::Error HWCDisplayVirtualDPU::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
133 if (NeedsGPUBypass()) {
134 MarkLayersForGPUBypass();
135 return HWC2::Error::None;
136 }
137
138 BuildLayerStack();
139 layer_stack_.output_buffer = &output_buffer_;
140 // If Output buffer of Virtual Display is not secure, set SKIP flag on the secure layers.
141 if (!output_buffer_.flags.secure && layer_stack_.flags.secure_present) {
142 for (auto hwc_layer : layer_set_) {
143 Layer *layer = hwc_layer->GetSDMLayer();
144 if (layer->input_buffer.flags.secure) {
145 layer_stack_.flags.skip_present = true;
146 layer->flags.skip = true;
147 }
148 }
149 }
150
151 return PrepareLayerStack(out_num_types, out_num_requests);
152 }
153
Present(shared_ptr<Fence> * out_retire_fence)154 HWC2::Error HWCDisplayVirtualDPU::Present(shared_ptr<Fence> *out_retire_fence) {
155 auto status = HWC2::Error::None;
156
157 if (!output_buffer_.buffer_id) {
158 return HWC2::Error::NoResources;
159 }
160
161 if (active_secure_sessions_.any()) {
162 return status;
163 }
164
165 layer_stack_.output_buffer = &output_buffer_;
166 if (display_paused_) {
167 validated_ = false;
168 flush_ = true;
169 }
170
171 status = HWCDisplay::CommitLayerStack();
172 if (status != HWC2::Error::None) {
173 return status;
174 }
175
176 DumpVDSBuffer();
177
178 status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
179
180 return status;
181 }
182
SetPanelLuminanceAttributes(float min_lum,float max_lum)183 HWC2::Error HWCDisplayVirtualDPU::SetPanelLuminanceAttributes(float min_lum, float max_lum) {
184 DisplayError err = display_intf_->SetPanelLuminanceAttributes(min_lum, max_lum);
185 if (err != kErrorNone) {
186 return HWC2::Error::BadParameter;
187 }
188 return HWC2::Error::None;
189 }
190
191 } // namespace sdm
192
193