summaryrefslogtreecommitdiff
path: root/libs/vr/libvrflinger/display_surface.h
blob: c8b1a078f70289bcf3c330c140cf6cf5fc9fd1b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SURFACE_H_
#define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SURFACE_H_

#include <pdx/file_handle.h>
#include <pdx/service.h>
#include <private/dvr/buffer_hub_queue_client.h>
#include <private/dvr/display_protocol.h>
#include <private/dvr/ring_buffer.h>

#include <functional>
#include <iterator>
#include <memory>
#include <string>
#include <vector>

#include "acquired_buffer.h"

namespace android {
namespace dvr {

class DisplayService;

enum class SurfaceType {
  Direct,
  Application,
};

class DisplaySurface : public pdx::Channel {
 public:
  static pdx::Status<std::shared_ptr<DisplaySurface>> Create(
      DisplayService* service, int surface_id, int process_id, int user_id,
      const display::SurfaceAttributes& attributes);

  ~DisplaySurface() override;

  DisplayService* service() const { return service_; }
  SurfaceType surface_type() const { return surface_type_; }
  int surface_id() const { return surface_id_; }
  int process_id() const { return process_id_; }
  int user_id() const { return user_id_; }

  bool visible() const { return visible_; }
  int z_order() const { return z_order_; }

  const display::SurfaceAttributes& attributes() const { return attributes_; }
  display::SurfaceUpdateFlags update_flags() const { return update_flags_; }

  virtual std::vector<int32_t> GetQueueIds() const { return {}; }

  bool IsUpdatePending() const {
    return update_flags_.value() != display::SurfaceUpdateFlags::None;
  }

 protected:
  DisplaySurface(DisplayService* service, SurfaceType surface_type,
                 int surface_id, int process_id, int user_id);

  // Utility to retrieve a shared pointer to this channel as the desired derived
  // type.
  template <
      typename T = DisplaySurface,
      typename = std::enable_if_t<std::is_base_of<DisplaySurface, T>::value>>
  std::shared_ptr<T> Self() {
    return std::static_pointer_cast<T>(shared_from_this());
  }

  virtual pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
      pdx::Message& message, const ProducerQueueConfig& config) = 0;

  // Registers a consumer queue with the event dispatcher in DisplayService. The
  // OnQueueEvent callback below is called to handle queue events.
  pdx::Status<void> RegisterQueue(
      const std::shared_ptr<ConsumerQueue>& consumer_queue);
  pdx::Status<void> UnregisterQueue(
      const std::shared_ptr<ConsumerQueue>& consumer_queue);

  // Called by the event dispatcher in DisplayService when a registered queue
  // event triggers. Executes on the event dispatcher thread.
  virtual void OnQueueEvent(
      const std::shared_ptr<ConsumerQueue>& consumer_queue, int events);

  void SurfaceUpdated(display::SurfaceUpdateFlags update_flags);
  void ClearUpdate();

  // Synchronizes access to mutable state below between message dispatch thread
  // and frame post thread.
  mutable std::mutex lock_;

 private:
  friend class DisplayService;
  friend class DisplayManagerService;

  // Dispatches display surface messages to the appropriate handlers. This
  // handler runs on the VrFlinger message dispatch thread.
  pdx::Status<void> HandleMessage(pdx::Message& message);

  pdx::Status<void> OnSetAttributes(
      pdx::Message& message, const display::SurfaceAttributes& attributes);
  pdx::Status<display::SurfaceInfo> OnGetSurfaceInfo(pdx::Message& message);

  DisplayService* service_;
  SurfaceType surface_type_;
  int surface_id_;
  int process_id_;
  int user_id_;

  display::SurfaceAttributes attributes_;
  display::SurfaceUpdateFlags update_flags_ = display::SurfaceUpdateFlags::None;

  // Subset of attributes that may be interpreted by the display service.
  bool visible_ = false;
  int z_order_ = 0;

  DisplaySurface(const DisplaySurface&) = delete;
  void operator=(const DisplaySurface&) = delete;
};

class ApplicationDisplaySurface : public DisplaySurface {
 public:
  ApplicationDisplaySurface(DisplayService* service, int surface_id,
                            int process_id, int user_id)
      : DisplaySurface(service, SurfaceType::Application, surface_id,
                       process_id, user_id) {}

  std::shared_ptr<ConsumerQueue> GetQueue(int32_t queue_id);
  std::vector<int32_t> GetQueueIds() const override;

 private:
  pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
      pdx::Message& message, const ProducerQueueConfig& config) override;
  void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
                    int events) override;

  // Accessed by both message dispatch thread and epoll event thread.
  std::unordered_map<int32_t, std::shared_ptr<ConsumerQueue>> consumer_queues_;
};

class DirectDisplaySurface : public DisplaySurface {
 public:
  DirectDisplaySurface(DisplayService* service, int surface_id, int process_id,
                       int user_id)
      : DisplaySurface(service, SurfaceType::Direct, surface_id, process_id,
                       user_id),
        acquired_buffers_(kMaxPostedBuffers),
        metadata_(nullptr) {}
  std::vector<int32_t> GetQueueIds() const override;
  bool IsBufferAvailable();
  bool IsBufferPosted();
  AcquiredBuffer AcquireCurrentBuffer();

  // Get the newest buffer. Up to one buffer will be skipped. If a buffer is
  // skipped, it will be stored in skipped_buffer if non null.
  AcquiredBuffer AcquireNewestAvailableBuffer(AcquiredBuffer* skipped_buffer);

 private:
  pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
      pdx::Message& message, const ProducerQueueConfig& config) override;
  void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
                    int events) override;

  // The capacity of the pending buffer queue. Should be enough to hold all the
  // buffers of this DisplaySurface, although in practice only 1 or 2 frames
  // will be pending at a time.
  static constexpr int kSurfaceBufferMaxCount = 4;
  static constexpr int kSurfaceViewMaxCount = 4;
  static constexpr int kMaxPostedBuffers =
      kSurfaceBufferMaxCount * kSurfaceViewMaxCount;

  // Returns whether a frame is available without locking the mutex.
  bool IsFrameAvailableNoLock() const;

  // Dequeue all available buffers from the consumer queue.
  void DequeueBuffersLocked();

  // In a triple-buffered surface, up to kMaxPostedBuffers buffers may be
  // posted and pending.
  RingBuffer<AcquiredBuffer> acquired_buffers_;

  std::shared_ptr<ConsumerQueue> direct_queue_;

  // Stores metadata when it dequeue buffers from consumer queue.
  std::unique_ptr<uint8_t[]> metadata_;
};

}  // namespace dvr
}  // namespace android

#endif  // ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SURFACE_H_