1#include "acquired_buffer.h"
2
3#include <log/log.h>
4#include <sync/sync.h>
5
6using android::pdx::LocalHandle;
7
8namespace android {
9namespace dvr {
10
11AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
12                               LocalHandle acquire_fence, std::size_t slot)
13    : buffer_(buffer), acquire_fence_(std::move(acquire_fence)), slot_(slot) {}
14
15AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
16                               int* error) {
17  LocalHandle fence;
18  const int ret = buffer->Acquire(&fence);
19
20  if (error)
21    *error = ret;
22
23  if (ret < 0) {
24    ALOGW("AcquiredBuffer::AcquiredBuffer: Failed to acquire buffer: %s",
25          strerror(-ret));
26    buffer_ = nullptr;
27    // Default construct sets acquire_fence_ to empty.
28  } else {
29    buffer_ = buffer;
30    acquire_fence_ = std::move(fence);
31  }
32}
33
34AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other) {
35  *this = std::move(other);
36}
37
38AcquiredBuffer::~AcquiredBuffer() { Release(LocalHandle(kEmptyFence)); }
39
40AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) {
41  if (this != &other) {
42    Release();
43
44    using std::swap;
45    swap(buffer_, other.buffer_);
46    swap(acquire_fence_, other.acquire_fence_);
47    swap(slot_, other.slot_);
48  }
49  return *this;
50}
51
52bool AcquiredBuffer::IsAvailable() const {
53  if (IsEmpty())
54    return false;
55
56  // Only check the fence if the acquire fence is not empty.
57  if (acquire_fence_) {
58    const int ret = sync_wait(acquire_fence_.Get(), 0);
59    ALOGD_IF(TRACE || (ret < 0 && errno != ETIME),
60             "AcquiredBuffer::IsAvailable: buffer_id=%d acquire_fence=%d "
61             "sync_wait()=%d errno=%d.",
62             buffer_->id(), acquire_fence_.Get(), ret, ret < 0 ? errno : 0);
63    if (ret == 0) {
64      // The fence is completed, so to avoid further calls to sync_wait we close
65      // it here.
66      acquire_fence_.Close();
67    }
68    return ret == 0;
69  } else {
70    return true;
71  }
72}
73
74LocalHandle AcquiredBuffer::ClaimAcquireFence() {
75  return std::move(acquire_fence_);
76}
77
78std::shared_ptr<BufferConsumer> AcquiredBuffer::ClaimBuffer() {
79  return std::move(buffer_);
80}
81
82int AcquiredBuffer::Release(LocalHandle release_fence) {
83  ALOGD_IF(TRACE, "AcquiredBuffer::Release: buffer_id=%d release_fence=%d",
84           buffer_ ? buffer_->id() : -1, release_fence.Get());
85  if (buffer_) {
86    const int ret = buffer_->ReleaseAsync();
87    if (ret < 0) {
88      ALOGE("AcquiredBuffer::Release: Failed to release buffer %d: %s",
89            buffer_->id(), strerror(-ret));
90      if (ret != -ESHUTDOWN)
91        return ret;
92    }
93
94    buffer_ = nullptr;
95  }
96
97  acquire_fence_.Close();
98  slot_ = 0;
99  return 0;
100}
101
102}  // namespace dvr
103}  // namespace android
104