summaryrefslogtreecommitdiff
path: root/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
blob: 8a490d9983a3c27a4a0092bbb9c025847eb05876 (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
#ifndef ANDROID_DVR_BUFFER_HUB_BASE_H_
#define ANDROID_DVR_BUFFER_HUB_BASE_H_

#include <vector>

#include <private/dvr/bufferhub_rpc.h>

namespace android {
namespace dvr {

// Base class of two types of BufferHub clients: dvr::ProducerBuffer and
// dvr::ConsumerBuffer.
class BufferHubBase : public pdx::Client {
 public:
  using LocalHandle = pdx::LocalHandle;
  using LocalChannelHandle = pdx::LocalChannelHandle;
  template <typename T>
  using Status = pdx::Status<T>;

  // Create a new consumer channel that is attached to the producer. Returns
  // a file descriptor for the new channel or a negative error code.
  Status<LocalChannelHandle> CreateConsumer();

  // Gets a blob buffer that was created with ProducerBuffer::CreateBlob.
  // Locking and Unlocking is handled internally. There's no need to Unlock
  // after calling this method.
  int GetBlobReadWritePointer(size_t size, void** addr);

  // Returns a dup'd file descriptor for accessing the blob shared memory. The
  // caller takes ownership of the file descriptor and must close it or pass on
  // ownership. Some GPU API extensions can take file descriptors to bind shared
  // memory gralloc buffers to GPU buffer objects.
  LocalHandle GetBlobFd() const {
    // Current GPU vendor puts the buffer allocation in one FD. If we change GPU
    // vendors and this is the wrong fd, late-latching and EDS will very clearly
    // stop working and we will need to correct this. The alternative is to use
    // a GL context in the pose service to allocate this buffer or to use the
    // ION API directly instead of gralloc.
    return LocalHandle(dup(native_handle()->data[0]));
  }

  using Client::event_fd;

  Status<int> GetEventMask(int events) {
    if (auto* client_channel = GetChannel()) {
      return client_channel->GetEventMask(events);
    } else {
      return pdx::ErrorStatus(EINVAL);
    }
  }

  std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
    if (auto* client_channel = GetChannel()) {
      return client_channel->GetEventSources();
    } else {
      return {};
    }
  }

  native_handle_t* native_handle() const {
    return const_cast<native_handle_t*>(buffer_.handle());
  }

  IonBuffer* buffer() { return &buffer_; }
  const IonBuffer* buffer() const { return &buffer_; }

  // Gets ID of the buffer client. All BufferHub clients derived from the same
  // buffer in bufferhubd share the same buffer id.
  int id() const { return id_; }

  // Gets the channel id of the buffer client. Each BufferHub client has its
  // system unique channel id.
  int cid() const { return cid_; }

  // Returns the buffer buffer state.
  uint32_t buffer_state() {
    return buffer_state_->load(std::memory_order_acquire);
  };

  // Returns whether the buffer is already released by all current clients.
  bool is_released() {
    return (buffer_state() &
            active_clients_bit_mask_->load(std::memory_order_acquire)) == 0;
  }

  // A state mask which is unique to a buffer hub client among all its siblings
  // sharing the same concrete graphic buffer.
  uint32_t client_state_mask() const { return client_state_mask_; }

  // The following methods return settings of the first buffer. Currently,
  // it is only possible to create multi-buffer BufferHubBases with the same
  // settings.
  uint32_t width() const { return buffer_.width(); }
  uint32_t height() const { return buffer_.height(); }
  uint32_t stride() const { return buffer_.stride(); }
  uint32_t format() const { return buffer_.format(); }
  uint32_t usage() const { return buffer_.usage(); }
  uint32_t layer_count() const { return buffer_.layer_count(); }

  uint64_t GetQueueIndex() const { return metadata_header_->queueIndex; }
  void SetQueueIndex(uint64_t index) { metadata_header_->queueIndex = index; }

 protected:
  explicit BufferHubBase(LocalChannelHandle channel);
  explicit BufferHubBase(const std::string& endpoint_path);
  virtual ~BufferHubBase();

  // Initialization helper.
  int ImportBuffer();

  // Check invalid metadata operation. Returns 0 if requested metadata is valid.
  int CheckMetadata(size_t user_metadata_size) const;

  // Send out the new fence by updating the shared fence (shared_release_fence
  // for producer and shared_acquire_fence for consumer). Note that during this
  // should only be used in LocalPost() or LocalRelease, and the shared fence
  // shouldn't be poll'ed by the other end.
  int UpdateSharedFence(const LocalHandle& new_fence,
                        const LocalHandle& shared_fence);

  // Locks the area specified by (x, y, width, height) for a specific usage. If
  // the usage is software then |addr| will be updated to point to the address
  // of the buffer in virtual memory. The caller should only access/modify the
  // pixels in the specified area. anything else is undefined behavior.
  int Lock(int usage, int x, int y, int width, int height, void** addr);

  // Must be called after Lock() when the caller has finished changing the
  // buffer.
  int Unlock();

  // IonBuffer that is shared between bufferhubd, producer, and consumers.
  size_t metadata_buf_size_{0};
  size_t user_metadata_size_{0};
  BufferHubDefs::MetadataHeader* metadata_header_ = nullptr;
  void* user_metadata_ptr_ = nullptr;
  std::atomic<uint32_t>* buffer_state_ = nullptr;
  std::atomic<uint32_t>* fence_state_ = nullptr;
  std::atomic<uint32_t>* active_clients_bit_mask_ = nullptr;

  LocalHandle shared_acquire_fence_;
  LocalHandle shared_release_fence_;

  // A local fence fd that holds the ownership of the fence fd on Post (for
  // producer) and Release (for consumer).
  LocalHandle pending_fence_fd_;

 private:
  BufferHubBase(const BufferHubBase&) = delete;
  void operator=(const BufferHubBase&) = delete;

  // Global id for the buffer that is consistent across processes. It is meant
  // for logging and debugging purposes only and should not be used for lookup
  // or any other functional purpose as a security precaution.
  int id_;

  // Channel id.
  int cid_;

  // Client bit mask which indicates the locations of this client object in the
  // buffer_state_.
  uint32_t client_state_mask_{0U};
  IonBuffer buffer_;
  IonBuffer metadata_buffer_;
};

}  // namespace dvr
}  // namespace android

#endif  // ANDROID_DVR_BUFFER_HUB_BASE_H_