blob: 66808ca02c7ec83a57402d06e132cdb740ff71fa [file] [log] [blame]
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001#include "display_surface.h"
2
3#include <utils/Trace.h>
4
5#include <private/dvr/platform_defines.h>
6
7#include "display_service.h"
8#include "hardware_composer.h"
9
10#define LOCAL_TRACE 1
11
12using android::pdx::BorrowedChannelHandle;
13using android::pdx::LocalChannelHandle;
14using android::pdx::Message;
15using android::pdx::RemoteChannelHandle;
16using android::pdx::Status;
17using android::pdx::rpc::DispatchRemoteMethod;
18using android::pdx::rpc::IfAnyOf;
19
20namespace android {
21namespace dvr {
22
23DisplaySurface::DisplaySurface(DisplayService* service, int surface_id,
24 int process_id, int width, int height,
25 int format, int usage, int flags)
26 : SurfaceChannel(service, surface_id, SurfaceTypeEnum::Normal,
27 sizeof(DisplaySurfaceMetadata)),
28 process_id_(process_id),
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -080029 acquired_buffers_(kMaxPostedBuffers),
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080030 video_mesh_surfaces_updated_(false),
31 width_(width),
32 height_(height),
33 format_(format),
34 usage_(usage),
35 flags_(flags),
36 client_visible_(false),
37 client_z_order_(0),
38 client_exclude_from_blur_(false),
39 client_blur_behind_(false),
40 manager_visible_(false),
41 manager_z_order_(0),
42 manager_blur_(0.0f),
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080043 layer_order_(0) {}
44
45DisplaySurface::~DisplaySurface() {
46 ALOGD_IF(LOCAL_TRACE,
47 "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
48 surface_id(), process_id_);
49}
50
51void DisplaySurface::ManagerSetVisible(bool visible) {
52 std::lock_guard<std::mutex> autolock(lock_);
53 manager_visible_ = visible;
54}
55
56void DisplaySurface::ManagerSetZOrder(int z_order) {
57 std::lock_guard<std::mutex> autolock(lock_);
58 manager_z_order_ = z_order;
59}
60
61void DisplaySurface::ManagerSetBlur(float blur) {
62 std::lock_guard<std::mutex> autolock(lock_);
63 manager_blur_ = blur;
64}
65
66void DisplaySurface::ClientSetVisible(bool visible) {
67 std::lock_guard<std::mutex> autolock(lock_);
68 client_visible_ = visible;
69}
70
71void DisplaySurface::ClientSetZOrder(int z_order) {
72 std::lock_guard<std::mutex> autolock(lock_);
73 client_z_order_ = z_order;
74}
75
76void DisplaySurface::ClientSetExcludeFromBlur(bool exclude_from_blur) {
77 std::lock_guard<std::mutex> autolock(lock_);
78 client_exclude_from_blur_ = exclude_from_blur;
79}
80
81void DisplaySurface::ClientSetBlurBehind(bool blur_behind) {
82 std::lock_guard<std::mutex> autolock(lock_);
83 client_blur_behind_ = blur_behind;
84}
85
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -080086void DisplaySurface::DequeueBuffersLocked() {
87 if (consumer_queue_ == nullptr) {
88 ALOGE(
89 "DisplaySurface::DequeueBuffersLocked: Consumer queue is not "
90 "initialized.");
91 return;
92 }
93
94 size_t slot;
95 uint64_t sequence;
96 while (true) {
97 LocalHandle acquire_fence;
98 auto buffer_consumer =
99 consumer_queue_->Dequeue(0, &slot, &sequence, &acquire_fence);
100 if (!buffer_consumer) {
101 ALOGD_IF(TRACE,
102 "DisplaySurface::DequeueBuffersLocked: We have dequeued all "
103 "available buffers.");
104 return;
105 }
106
107 if (!IsVisible()) {
108 ATRACE_NAME("DropFrameOnInvisibleSurface");
109 ALOGD_IF(TRACE,
110 "DisplaySurface::DequeueBuffersLocked: Discarding buffer_id=%d "
111 "on invisible surface.",
112 buffer_consumer->id());
113 buffer_consumer->Discard();
114 continue;
115 }
116
117 if (acquired_buffers_.IsFull()) {
118 ALOGE(
119 "DisplaySurface::DequeueBuffersLocked: Posted buffers full, "
120 "overwriting.");
121 acquired_buffers_.PopBack();
122 }
123
124 acquired_buffers_.Append(
125 AcquiredBuffer(buffer_consumer, std::move(acquire_fence), sequence));
126 }
127}
128
129AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
130 std::lock_guard<std::mutex> autolock(lock_);
131 DequeueBuffersLocked();
132
133 if (acquired_buffers_.IsEmpty()) {
134 ALOGE(
135 "DisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer when "
136 "none are posted.");
137 return AcquiredBuffer();
138 }
139 AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
140 acquired_buffers_.PopFront();
141 ALOGD_IF(TRACE, "DisplaySurface::AcquireCurrentBuffer: buffer: %p",
142 buffer.buffer().get());
143 return buffer;
144}
145
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800146AcquiredBuffer DisplaySurface::AcquireNewestAvailableBuffer(
147 AcquiredBuffer* skipped_buffer) {
148 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800149 DequeueBuffersLocked();
150
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800151 AcquiredBuffer buffer;
152 int frames = 0;
153 // Basic latency stopgap for when the application misses a frame:
154 // If the application recovers on the 2nd or 3rd (etc) frame after
155 // missing, this code will skip frames to catch up by checking if
156 // the next frame is also available.
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800157 while (!acquired_buffers_.IsEmpty() &&
158 acquired_buffers_.Front().IsAvailable()) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800159 // Capture the skipped buffer into the result parameter.
160 // Note that this API only supports skipping one buffer per vsync.
161 if (frames > 0 && skipped_buffer)
162 *skipped_buffer = std::move(buffer);
163 ++frames;
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800164 buffer = std::move(acquired_buffers_.Front());
165 acquired_buffers_.PopFront();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800166 if (frames == 2)
167 break;
168 }
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800169 ALOGD_IF(TRACE, "DisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
170 buffer.buffer().get());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800171 return buffer;
172}
173
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800174bool DisplaySurface::IsBufferAvailable() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800175 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800176 DequeueBuffersLocked();
177
178 return !acquired_buffers_.IsEmpty() &&
179 acquired_buffers_.Front().IsAvailable();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800180}
181
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800182bool DisplaySurface::IsBufferPosted() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800183 std::lock_guard<std::mutex> autolock(lock_);
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800184 DequeueBuffersLocked();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800185
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800186 return !acquired_buffers_.IsEmpty();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800187}
188
189int DisplaySurface::HandleMessage(pdx::Message& message) {
190 switch (message.GetOp()) {
191 case DisplayRPC::SetAttributes::Opcode:
192 DispatchRemoteMethod<DisplayRPC::SetAttributes>(
193 *this, &DisplaySurface::OnClientSetAttributes, message);
194 break;
195
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800196 case DisplayRPC::CreateBufferQueue::Opcode:
197 DispatchRemoteMethod<DisplayRPC::CreateBufferQueue>(
198 *this, &DisplaySurface::OnCreateBufferQueue, message);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800199 break;
200
201 case DisplayRPC::CreateVideoMeshSurface::Opcode:
202 DispatchRemoteMethod<DisplayRPC::CreateVideoMeshSurface>(
203 *this, &DisplaySurface::OnCreateVideoMeshSurface, message);
204 break;
205
206 default:
207 return SurfaceChannel::HandleMessage(message);
208 }
209
210 return 0;
211}
212
213int DisplaySurface::OnClientSetAttributes(
214 pdx::Message& /*message*/, const DisplaySurfaceAttributes& attributes) {
215 for (const auto& attribute : attributes) {
216 const auto& key = attribute.first;
217 const auto* variant = &attribute.second;
218 bool invalid_value = false;
219 switch (key) {
220 case DisplaySurfaceAttributeEnum::ZOrder:
221 invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
222 variant, [this](const auto& value) {
223 DisplaySurface::ClientSetZOrder(value);
224 });
225 break;
226 case DisplaySurfaceAttributeEnum::Visible:
227 invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
228 variant, [this](const auto& value) {
229 DisplaySurface::ClientSetVisible(value);
230 });
231 break;
232 case DisplaySurfaceAttributeEnum::ExcludeFromBlur:
233 invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
234 variant, [this](const auto& value) {
235 DisplaySurface::ClientSetExcludeFromBlur(value);
236 });
237 break;
238 case DisplaySurfaceAttributeEnum::BlurBehind:
239 invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
240 variant, [this](const auto& value) {
241 DisplaySurface::ClientSetBlurBehind(value);
242 });
243 break;
244 default:
245 ALOGW(
246 "DisplaySurface::OnClientSetAttributes: Unrecognized attribute %d "
247 "surface_id=%d",
248 key, surface_id());
249 break;
250 }
251
252 if (invalid_value) {
253 ALOGW(
254 "DisplaySurface::OnClientSetAttributes: Failed to set display "
255 "surface attribute '%s' because of incompatible type: %d",
256 DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index());
257 }
258 }
259
260 service()->NotifyDisplayConfigurationUpdate();
261 return 0;
262}
263
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800264LocalChannelHandle DisplaySurface::OnCreateBufferQueue(Message& message) {
265 ATRACE_NAME("DisplaySurface::OnCreateBufferQueue");
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800266
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800267 if (consumer_queue_ != nullptr) {
268 ALOGE(
269 "DisplaySurface::OnCreateBufferQueue: A ProdcuerQueue has already been "
270 "created and transported to DisplayClient.");
271 REPLY_ERROR_RETURN(message, EALREADY, {});
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800272 }
273
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800274 auto producer = ProducerQueue::Create<uint64_t>();
275 consumer_queue_ = producer->CreateConsumerQueue();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800276
Jiwen 'Steve' Caia3613612017-03-08 17:41:48 -0800277 return std::move(producer->GetChannelHandle());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800278}
279
280RemoteChannelHandle DisplaySurface::OnCreateVideoMeshSurface(
281 pdx::Message& message) {
282 if (flags_ & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION) {
283 ALOGE(
284 "DisplaySurface::OnCreateVideoMeshSurface: system distorion is "
285 "disabled on this display surface, cannot create VideoMeshSurface on "
286 "top of it.");
287 REPLY_ERROR_RETURN(message, EINVAL, {});
288 }
289
290 int channel_id;
291 auto status = message.PushChannel(0, nullptr, &channel_id);
292
293 if (!status) {
294 ALOGE(
295 "DisplaySurface::OnCreateVideoMeshSurface: failed to push channel: %s",
296 status.GetErrorMessage().c_str());
297 REPLY_ERROR_RETURN(message, ENOMEM, {});
298 }
299
300 auto surface = std::make_shared<VideoMeshSurface>(service(), channel_id);
301 const int ret = service()->SetChannel(channel_id, surface);
302 if (ret < 0) {
303 ALOGE(
304 "DisplaySurface::OnCreateVideoMeshSurface: failed to set new video "
305 "mesh surface channel: %s",
306 strerror(-ret));
307 REPLY_ERROR_RETURN(message, ENOMEM, {});
308 }
309
310 {
311 std::lock_guard<std::mutex> autolock(lock_);
312 pending_video_mesh_surfaces_.push_back(surface);
313 video_mesh_surfaces_updated_ = true;
314 }
315
316 return status.take();
317}
318
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800319std::vector<std::shared_ptr<VideoMeshSurface>>
320DisplaySurface::GetVideoMeshSurfaces() {
321 std::lock_guard<std::mutex> autolock(lock_);
322 std::vector<std::shared_ptr<VideoMeshSurface>> surfaces;
323
324 for (auto& surface : pending_video_mesh_surfaces_) {
325 if (auto video_surface = surface.lock()) {
326 surfaces.push_back(video_surface);
327 } else {
328 ALOGE("Unable to lock video mesh surface.");
329 }
330 }
331
332 pending_video_mesh_surfaces_.clear();
333 video_mesh_surfaces_updated_ = false;
334 return surfaces;
335}
336
337} // namespace dvr
338} // namespace android