display_surface.cpp revision f0a7bd033941e26e380232a0515e903cf8e678e5
1#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),
29      acquired_buffers_(kMaxPostedBuffers),
30      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),
43      layer_order_(0),
44      allocated_buffer_index_(0) {}
45
46DisplaySurface::~DisplaySurface() {
47  ALOGD_IF(LOCAL_TRACE,
48           "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
49           surface_id(), process_id_);
50}
51
52void DisplaySurface::ManagerSetVisible(bool visible) {
53  std::lock_guard<std::mutex> autolock(lock_);
54  manager_visible_ = visible;
55}
56
57void DisplaySurface::ManagerSetZOrder(int z_order) {
58  std::lock_guard<std::mutex> autolock(lock_);
59  manager_z_order_ = z_order;
60}
61
62void DisplaySurface::ManagerSetBlur(float blur) {
63  std::lock_guard<std::mutex> autolock(lock_);
64  manager_blur_ = blur;
65}
66
67void DisplaySurface::ClientSetVisible(bool visible) {
68  std::lock_guard<std::mutex> autolock(lock_);
69  client_visible_ = visible;
70}
71
72void DisplaySurface::ClientSetZOrder(int z_order) {
73  std::lock_guard<std::mutex> autolock(lock_);
74  client_z_order_ = z_order;
75}
76
77void DisplaySurface::ClientSetExcludeFromBlur(bool exclude_from_blur) {
78  std::lock_guard<std::mutex> autolock(lock_);
79  client_exclude_from_blur_ = exclude_from_blur;
80}
81
82void DisplaySurface::ClientSetBlurBehind(bool blur_behind) {
83  std::lock_guard<std::mutex> autolock(lock_);
84  client_blur_behind_ = blur_behind;
85}
86
87void DisplaySurface::DequeueBuffersLocked() {
88  if (consumer_queue_ == nullptr) {
89    ALOGE(
90        "DisplaySurface::DequeueBuffersLocked: Consumer queue is not "
91        "initialized.");
92    return;
93  }
94
95  size_t slot;
96  uint64_t sequence;
97  while (true) {
98    LocalHandle acquire_fence;
99    auto buffer_consumer =
100        consumer_queue_->Dequeue(0, &slot, &sequence, &acquire_fence);
101    if (!buffer_consumer) {
102      ALOGD_IF(TRACE,
103               "DisplaySurface::DequeueBuffersLocked: We have dequeued all "
104               "available buffers.");
105      return;
106    }
107
108    // Save buffer index, associated with the buffer id so that it can be looked
109    // up later.
110    int buffer_id = buffer_consumer->id();
111    if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) {
112      buffer_id_to_index_[buffer_id] = allocated_buffer_index_;
113      ++allocated_buffer_index_;
114    }
115
116    if (!IsVisible()) {
117      ATRACE_NAME("DropFrameOnInvisibleSurface");
118      ALOGD_IF(TRACE,
119               "DisplaySurface::DequeueBuffersLocked: Discarding buffer_id=%d "
120               "on invisible surface.",
121               buffer_consumer->id());
122      buffer_consumer->Discard();
123      continue;
124    }
125
126    if (acquired_buffers_.IsFull()) {
127      ALOGE(
128          "DisplaySurface::DequeueBuffersLocked: Posted buffers full, "
129          "overwriting.");
130      acquired_buffers_.PopBack();
131    }
132
133    acquired_buffers_.Append(
134        AcquiredBuffer(buffer_consumer, std::move(acquire_fence), sequence));
135  }
136}
137
138AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
139  std::lock_guard<std::mutex> autolock(lock_);
140  DequeueBuffersLocked();
141
142  if (acquired_buffers_.IsEmpty()) {
143    ALOGE(
144        "DisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer when "
145        "none are posted.");
146    return AcquiredBuffer();
147  }
148  AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
149  acquired_buffers_.PopFront();
150  ALOGD_IF(TRACE, "DisplaySurface::AcquireCurrentBuffer: buffer: %p",
151           buffer.buffer().get());
152  return buffer;
153}
154
155AcquiredBuffer DisplaySurface::AcquireNewestAvailableBuffer(
156    AcquiredBuffer* skipped_buffer) {
157  std::lock_guard<std::mutex> autolock(lock_);
158  DequeueBuffersLocked();
159
160  AcquiredBuffer buffer;
161  int frames = 0;
162  // Basic latency stopgap for when the application misses a frame:
163  // If the application recovers on the 2nd or 3rd (etc) frame after
164  // missing, this code will skip frames to catch up by checking if
165  // the next frame is also available.
166  while (!acquired_buffers_.IsEmpty() &&
167         acquired_buffers_.Front().IsAvailable()) {
168    // Capture the skipped buffer into the result parameter.
169    // Note that this API only supports skipping one buffer per vsync.
170    if (frames > 0 && skipped_buffer)
171      *skipped_buffer = std::move(buffer);
172    ++frames;
173    buffer = std::move(acquired_buffers_.Front());
174    acquired_buffers_.PopFront();
175    if (frames == 2)
176      break;
177  }
178  ALOGD_IF(TRACE, "DisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
179           buffer.buffer().get());
180  return buffer;
181}
182
183uint32_t DisplaySurface::GetRenderBufferIndex(int buffer_id) {
184  std::lock_guard<std::mutex> autolock(lock_);
185
186  if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) {
187    ALOGW("DisplaySurface::GetRenderBufferIndex: unknown buffer_id %d.",
188          buffer_id);
189    return 0;
190  }
191  return buffer_id_to_index_[buffer_id];
192}
193
194bool DisplaySurface::IsBufferAvailable() {
195  std::lock_guard<std::mutex> autolock(lock_);
196  DequeueBuffersLocked();
197
198  return !acquired_buffers_.IsEmpty() &&
199         acquired_buffers_.Front().IsAvailable();
200}
201
202bool DisplaySurface::IsBufferPosted() {
203  std::lock_guard<std::mutex> autolock(lock_);
204  DequeueBuffersLocked();
205
206  return !acquired_buffers_.IsEmpty();
207}
208
209pdx::Status<void> DisplaySurface::HandleMessage(pdx::Message& message) {
210  switch (message.GetOp()) {
211    case DisplayRPC::SetAttributes::Opcode:
212      DispatchRemoteMethod<DisplayRPC::SetAttributes>(
213          *this, &DisplaySurface::OnClientSetAttributes, message);
214      break;
215
216    case DisplayRPC::CreateBufferQueue::Opcode:
217      DispatchRemoteMethod<DisplayRPC::CreateBufferQueue>(
218          *this, &DisplaySurface::OnCreateBufferQueue, message);
219      break;
220
221    case DisplayRPC::CreateVideoMeshSurface::Opcode:
222      DispatchRemoteMethod<DisplayRPC::CreateVideoMeshSurface>(
223          *this, &DisplaySurface::OnCreateVideoMeshSurface, message);
224      break;
225
226    default:
227      return SurfaceChannel::HandleMessage(message);
228  }
229
230  return {};
231}
232
233int DisplaySurface::OnClientSetAttributes(
234    pdx::Message& /*message*/, const DisplaySurfaceAttributes& attributes) {
235  for (const auto& attribute : attributes) {
236    const auto& key = attribute.first;
237    const auto* variant = &attribute.second;
238    bool invalid_value = false;
239    switch (key) {
240      case DisplaySurfaceAttributeEnum::ZOrder:
241        invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
242            variant, [this](const auto& value) {
243              DisplaySurface::ClientSetZOrder(value);
244            });
245        break;
246      case DisplaySurfaceAttributeEnum::Visible:
247        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
248            variant, [this](const auto& value) {
249              DisplaySurface::ClientSetVisible(value);
250            });
251        break;
252      case DisplaySurfaceAttributeEnum::ExcludeFromBlur:
253        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
254            variant, [this](const auto& value) {
255              DisplaySurface::ClientSetExcludeFromBlur(value);
256            });
257        break;
258      case DisplaySurfaceAttributeEnum::BlurBehind:
259        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
260            variant, [this](const auto& value) {
261              DisplaySurface::ClientSetBlurBehind(value);
262            });
263        break;
264      default:
265        ALOGW(
266            "DisplaySurface::OnClientSetAttributes: Unrecognized attribute %d "
267            "surface_id=%d",
268            key, surface_id());
269        break;
270    }
271
272    if (invalid_value) {
273      ALOGW(
274          "DisplaySurface::OnClientSetAttributes: Failed to set display "
275          "surface attribute '%s' because of incompatible type: %d",
276          DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index());
277    }
278  }
279
280  service()->NotifyDisplayConfigurationUpdate();
281  return 0;
282}
283
284LocalChannelHandle DisplaySurface::OnCreateBufferQueue(Message& message) {
285  ATRACE_NAME("DisplaySurface::OnCreateBufferQueue");
286
287  if (consumer_queue_ != nullptr) {
288    ALOGE(
289        "DisplaySurface::OnCreateBufferQueue: A ProdcuerQueue has already been "
290        "created and transported to DisplayClient.");
291    REPLY_ERROR_RETURN(message, EALREADY, {});
292  }
293
294  auto producer = ProducerQueue::Create<uint64_t>();
295  consumer_queue_ = producer->CreateConsumerQueue();
296
297  return std::move(producer->GetChannelHandle());
298}
299
300RemoteChannelHandle DisplaySurface::OnCreateVideoMeshSurface(
301    pdx::Message& message) {
302  if (flags_ & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION) {
303    ALOGE(
304        "DisplaySurface::OnCreateVideoMeshSurface: system distortion is "
305        "disabled on this display surface, cannot create VideoMeshSurface on "
306        "top of it.");
307    REPLY_ERROR_RETURN(message, EINVAL, {});
308  }
309
310  int channel_id;
311  auto status = message.PushChannel(0, nullptr, &channel_id);
312  if (!status) {
313    ALOGE(
314        "DisplaySurface::OnCreateVideoMeshSurface: failed to push channel: %s",
315        status.GetErrorMessage().c_str());
316    REPLY_ERROR_RETURN(message, status.error(), {});
317  }
318
319  auto surface = std::make_shared<VideoMeshSurface>(service(), channel_id);
320  auto channel_status = service()->SetChannel(channel_id, surface);
321  if (!channel_status) {
322    ALOGE(
323        "DisplaySurface::OnCreateVideoMeshSurface: failed to set new video "
324        "mesh surface channel: %s",
325        channel_status.GetErrorMessage().c_str());
326    REPLY_ERROR_RETURN(message, channel_status.error(), {});
327  }
328
329  {
330    std::lock_guard<std::mutex> autolock(lock_);
331    pending_video_mesh_surfaces_.push_back(surface);
332    video_mesh_surfaces_updated_ = true;
333  }
334
335  return status.take();
336}
337
338std::vector<std::shared_ptr<VideoMeshSurface>>
339DisplaySurface::GetVideoMeshSurfaces() {
340  std::lock_guard<std::mutex> autolock(lock_);
341  std::vector<std::shared_ptr<VideoMeshSurface>> surfaces;
342
343  for (auto& surface : pending_video_mesh_surfaces_) {
344    if (auto video_surface = surface.lock()) {
345      surfaces.push_back(video_surface);
346    } else {
347      ALOGE("Unable to lock video mesh surface.");
348    }
349  }
350
351  pending_video_mesh_surfaces_.clear();
352  video_mesh_surfaces_updated_ = false;
353  return surfaces;
354}
355
356}  // namespace dvr
357}  // namespace android
358