blob: c464c983c04256faff24d3816b6526e6b45392c1 [file] [log] [blame]
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001#include "display_service.h"
2
3#include <vector>
4
5#include <pdx/default_transport/service_endpoint.h>
6#include <pdx/rpc/remote_method.h>
7#include <private/dvr/composite_hmd.h>
8#include <private/dvr/display_rpc.h>
9#include <private/dvr/display_types.h>
10#include <private/dvr/lucid_metrics.h>
11#include <private/dvr/numeric.h>
12#include <private/dvr/polynomial_radial_distortion.h>
13#include <private/dvr/types.h>
14
15using android::pdx::Channel;
16using android::pdx::Message;
17using android::pdx::default_transport::Endpoint;
18using android::pdx::rpc::DispatchRemoteMethod;
19using android::pdx::rpc::WrapBuffer;
20
21namespace android {
22namespace dvr {
23
24DisplayService::DisplayService() : DisplayService(nullptr) {}
25
26DisplayService::DisplayService(Hwc2::Composer* hidl)
27 : BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
28 hardware_composer_(hidl) {}
29
30std::string DisplayService::DumpState(size_t max_length) {
31 std::vector<char> buffer(max_length);
32 uint32_t max_len_p = static_cast<uint32_t>(max_length);
33 hardware_composer_.Dump(buffer.data(), &max_len_p);
34 return std::string(buffer.data());
35}
36
37void DisplayService::OnChannelClose(pdx::Message& /*message*/,
38 const std::shared_ptr<Channel>& channel) {
39 auto surface = std::static_pointer_cast<SurfaceChannel>(channel);
40 if (surface && surface->type() == SurfaceTypeEnum::Normal) {
41 auto display_surface = std::static_pointer_cast<DisplaySurface>(surface);
42 display_surface->ManagerSetVisible(false);
43 display_surface->ClientSetVisible(false);
44 NotifyDisplayConfigurationUpdate();
45 }
46 // TODO(jwcai) Handle ChannelClose of VideoMeshSurface.
47}
48
49// First-level dispatch for display service messages. Directly handles messages
50// that are independent of the display surface (metrics, creation) and routes
51// surface-specific messages to the per-instance handlers.
52int DisplayService::HandleMessage(pdx::Message& message) {
53 auto channel = message.GetChannel<SurfaceChannel>();
54
55 switch (message.GetOp()) {
56 case DisplayRPC::GetMetrics::Opcode:
57 DispatchRemoteMethod<DisplayRPC::GetMetrics>(
58 *this, &DisplayService::OnGetMetrics, message);
59 return 0;
60
61 case DisplayRPC::GetEdsCapture::Opcode:
62 DispatchRemoteMethod<DisplayRPC::GetEdsCapture>(
63 *this, &DisplayService::OnGetEdsCapture, message);
64 return 0;
65
66 case DisplayRPC::CreateSurface::Opcode:
67 DispatchRemoteMethod<DisplayRPC::CreateSurface>(
68 *this, &DisplayService::OnCreateSurface, message);
69 return 0;
70
71 case DisplayRPC::EnterVrMode::Opcode:
72 DispatchRemoteMethod<DisplayRPC::EnterVrMode>(
73 *this, &DisplayService::OnEnterVrMode, message);
74 return 0;
75
76 case DisplayRPC::ExitVrMode::Opcode:
77 DispatchRemoteMethod<DisplayRPC::ExitVrMode>(
78 *this, &DisplayService::OnExitVrMode, message);
79 return 0;
80
81 case DisplayRPC::SetViewerParams::Opcode:
82 DispatchRemoteMethod<DisplayRPC::SetViewerParams>(
83 *this, &DisplayService::OnSetViewerParams, message);
84 return 0;
85
86 // Direct the surface specific messages to the surface instance.
87 case DisplayRPC::AllocateBuffer::Opcode:
88 case DisplayRPC::SetAttributes::Opcode:
89 case DisplayRPC::GetMetadataBuffer::Opcode:
90 case DisplayRPC::CreateVideoMeshSurface::Opcode:
91 case DisplayRPC::VideoMeshSurfaceCreateProducerQueue::Opcode:
92 return HandleSurfaceMessage(message);
93
94 default:
95 return Service::HandleMessage(message);
96 }
97}
98
99SystemDisplayMetrics DisplayService::OnGetMetrics(pdx::Message& message) {
100 const Compositor* compositor = hardware_composer_.GetCompositor();
101 if (compositor == nullptr)
102 REPLY_ERROR_RETURN(message, EINVAL, {});
103
104 HeadMountMetrics head_mount = compositor->head_mount_metrics();
105 CompositeHmd hmd(head_mount, hardware_composer_.GetHmdDisplayMetrics());
106 vec2i distorted_render_size = hmd.GetRecommendedRenderTargetSize();
107 FieldOfView left_fov = hmd.GetEyeFov(kLeftEye);
108 FieldOfView right_fov = hmd.GetEyeFov(kRightEye);
109
110 SystemDisplayMetrics metrics;
111
112 metrics.display_native_width = GetDisplayMetrics().width;
113 metrics.display_native_height = GetDisplayMetrics().height;
114 metrics.display_x_dpi = GetDisplayMetrics().dpi.x;
115 metrics.display_y_dpi = GetDisplayMetrics().dpi.y;
116 metrics.distorted_width = distorted_render_size[0];
117 metrics.distorted_height = distorted_render_size[1];
118 metrics.vsync_period_ns =
119 hardware_composer_.native_display_metrics().vsync_period_ns;
120 metrics.hmd_ipd_mm = 0;
121 metrics.inter_lens_distance_m = head_mount.GetInterLensDistance();
122 metrics.left_fov_lrbt[0] = left_fov.GetLeft();
123 metrics.left_fov_lrbt[1] = left_fov.GetRight();
124 metrics.left_fov_lrbt[2] = left_fov.GetBottom();
125 metrics.left_fov_lrbt[3] = left_fov.GetTop();
126 metrics.right_fov_lrbt[0] = right_fov.GetLeft();
127 metrics.right_fov_lrbt[1] = right_fov.GetRight();
128 metrics.right_fov_lrbt[2] = right_fov.GetBottom();
129 metrics.right_fov_lrbt[3] = right_fov.GetTop();
130
131 return metrics;
132}
133
134// Creates a new DisplaySurface and associates it with this channel. This may
135// only be done once per channel.
136int DisplayService::OnCreateSurface(pdx::Message& message, int width,
137 int height, int format, int usage,
138 DisplaySurfaceFlags flags) {
139 // A surface may only be created once per channel.
140 if (message.GetChannel())
141 return -EINVAL;
142
143 ALOGI_IF(TRACE, "DisplayService::OnCreateSurface: cid=%d",
144 message.GetChannelId());
145
146 // Use the channel id as the unique surface id.
147 const int surface_id = message.GetChannelId();
148 const int process_id = message.GetProcessId();
149
150 ALOGI_IF(TRACE,
151 "DisplayService::OnCreateSurface: surface_id=%d process_id=%d "
152 "width=%d height=%d format=%x usage=%x flags=%x",
153 surface_id, process_id, width, height, format, usage, flags);
154
155 // TODO(eieio,jbates): Validate request parameters.
156 auto channel = std::make_shared<DisplaySurface>(
157 this, surface_id, process_id, width, height, format, usage, flags);
158
159 message.SetChannel(channel);
160 NotifyDisplayConfigurationUpdate();
161 return 0;
162}
163
164DisplayRPC::ByteBuffer DisplayService::OnGetEdsCapture(pdx::Message& message) {
165 Compositor* compositor = hardware_composer_.GetCompositor();
166 if (compositor == nullptr)
167 REPLY_ERROR_RETURN(message, EINVAL, {});
168
169 std::vector<std::uint8_t> buffer(sizeof(LateLatchOutput));
170
171 if (!compositor->GetLastEdsPose(
172 reinterpret_cast<LateLatchOutput*>(buffer.data()))) {
173 REPLY_ERROR_RETURN(message, EPERM, {});
174 }
175
176 return WrapBuffer(std::move(buffer));
177}
178
179int DisplayService::OnEnterVrMode(pdx::Message& /*message*/) {
180 hardware_composer_.Resume();
181 return 0;
182}
183
184int DisplayService::OnExitVrMode(pdx::Message& /*message*/) {
185 hardware_composer_.Suspend();
186 return 0;
187}
188
189void DisplayService::OnSetViewerParams(pdx::Message& message,
190 const ViewerParams& view_params) {
191 Compositor* compositor = hardware_composer_.GetCompositor();
192 if (compositor == nullptr)
193 REPLY_ERROR_RETURN(message, EINVAL);
194
195 FieldOfView left(55.0f, 55.0f, 55.0f, 55.0f);
196 FieldOfView right(55.0f, 55.0f, 55.0f, 55.0f);
197 if (view_params.left_eye_field_of_view_angles.size() >= 4) {
198 left = FieldOfView(ToRad(view_params.left_eye_field_of_view_angles[0]),
199 ToRad(view_params.left_eye_field_of_view_angles[1]),
200 ToRad(view_params.left_eye_field_of_view_angles[2]),
201 ToRad(view_params.left_eye_field_of_view_angles[3]));
202 right = FieldOfView(ToRad(view_params.left_eye_field_of_view_angles[1]),
203 ToRad(view_params.left_eye_field_of_view_angles[0]),
204 ToRad(view_params.left_eye_field_of_view_angles[2]),
205 ToRad(view_params.left_eye_field_of_view_angles[3]));
206 }
207
208 std::shared_ptr<ColorChannelDistortion> red_distortion;
209 std::shared_ptr<ColorChannelDistortion> green_distortion;
210 std::shared_ptr<ColorChannelDistortion> blue_distortion;
211
212 // We should always have a red distortion.
213 LOG_FATAL_IF(view_params.distortion_coefficients_r.empty());
214 red_distortion = std::make_shared<PolynomialRadialDistortion>(
215 view_params.distortion_coefficients_r);
216
217 if (!view_params.distortion_coefficients_g.empty()) {
218 green_distortion = std::make_shared<PolynomialRadialDistortion>(
219 view_params.distortion_coefficients_g);
220 }
221
222 if (!view_params.distortion_coefficients_b.empty()) {
223 blue_distortion = std::make_shared<PolynomialRadialDistortion>(
224 view_params.distortion_coefficients_b);
225 }
226
227 HeadMountMetrics::EyeOrientation left_orientation =
228 HeadMountMetrics::EyeOrientation::kCCW0Degrees;
229 HeadMountMetrics::EyeOrientation right_orientation =
230 HeadMountMetrics::EyeOrientation::kCCW0Degrees;
231
232 if (view_params.eye_orientations.size() > 1) {
233 left_orientation = static_cast<HeadMountMetrics::EyeOrientation>(
234 view_params.eye_orientations[0]);
235 right_orientation = static_cast<HeadMountMetrics::EyeOrientation>(
236 view_params.eye_orientations[1]);
237 }
238
239 HeadMountMetrics head_mount_metrics(
240 view_params.inter_lens_distance, view_params.tray_to_lens_distance,
241 view_params.screen_to_lens_distance,
242 static_cast<HeadMountMetrics::VerticalAlignment>(
243 view_params.vertical_alignment),
244 left, right, red_distortion, green_distortion, blue_distortion,
245 left_orientation, right_orientation,
246 view_params.screen_center_to_lens_distance);
247
248 compositor->UpdateHeadMountMetrics(head_mount_metrics);
249}
250
251// Calls the message handler for the DisplaySurface associated with this
252// channel.
253int DisplayService::HandleSurfaceMessage(pdx::Message& message) {
254 auto surface = std::static_pointer_cast<SurfaceChannel>(message.GetChannel());
255 ALOGW_IF(!surface,
256 "DisplayService::HandleSurfaceMessage: surface is nullptr!");
257
258 if (surface)
259 return surface->HandleMessage(message);
260 else
261 REPLY_ERROR_RETURN(message, EINVAL, 0);
262}
263
264std::shared_ptr<DisplaySurface> DisplayService::GetDisplaySurface(
265 int surface_id) const {
266 return std::static_pointer_cast<DisplaySurface>(GetChannel(surface_id));
267}
268
269std::vector<std::shared_ptr<DisplaySurface>>
270DisplayService::GetDisplaySurfaces() const {
271 return GetChannels<DisplaySurface>();
272}
273
274std::vector<std::shared_ptr<DisplaySurface>>
275DisplayService::GetVisibleDisplaySurfaces() const {
276 std::vector<std::shared_ptr<DisplaySurface>> visible_surfaces;
277
278 ForEachDisplaySurface(
279 [&](const std::shared_ptr<DisplaySurface>& surface) mutable {
280 if (surface->IsVisible())
281 visible_surfaces.push_back(surface);
282 });
283
284 return visible_surfaces;
285}
286
287int DisplayService::UpdateActiveDisplaySurfaces() {
288 auto visible_surfaces = GetVisibleDisplaySurfaces();
289
290 // Sort the surfaces based on manager z order first, then client z order.
291 std::sort(visible_surfaces.begin(), visible_surfaces.end(),
292 [](const std::shared_ptr<DisplaySurface>& a,
293 const std::shared_ptr<DisplaySurface>& b) {
294 return a->manager_z_order() != b->manager_z_order()
295 ? a->manager_z_order() < b->manager_z_order()
296 : a->client_z_order() < b->client_z_order();
297 });
298
299 ALOGD_IF(TRACE,
300 "DisplayService::UpdateActiveDisplaySurfaces: %zd visible surfaces",
301 visible_surfaces.size());
302
303 // TODO(jbates) Have the shell manage blurred layers.
304 bool blur_requested = false;
305 auto end = visible_surfaces.crend();
306 for (auto it = visible_surfaces.crbegin(); it != end; ++it) {
307 auto surface = *it;
308 // Surfaces with exclude_from_blur==true are not blurred
309 // and are excluded from blur computation of other layers.
310 if (surface->client_exclude_from_blur()) {
311 surface->ManagerSetBlur(0.0f);
312 continue;
313 }
314 surface->ManagerSetBlur(blur_requested ? 1.0f : 0.0f);
315 if (surface->client_blur_behind())
316 blur_requested = true;
317 }
318 return hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
319}
320
321void DisplayService::SetDisplayConfigurationUpdateNotifier(
322 DisplayConfigurationUpdateNotifier update_notifier) {
323 update_notifier_ = update_notifier;
324}
325
326void DisplayService::NotifyDisplayConfigurationUpdate() {
327 if (update_notifier_)
328 update_notifier_();
329}
330
331} // namespace dvr
332} // namespace android