Add libvrflinger for use in SurfaceFlinger
A separate CL uses this code from SurfaceFlinger.
Bug: None
Test: Manually ran modified SurfaceFlinger
Change-Id: I34588df1365588c0a0265e1e2325e3dd5516206a
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
new file mode 100644
index 0000000..5a3aa7f
--- /dev/null
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -0,0 +1,100 @@
+#include "acquired_buffer.h"
+
+#include <log/log.h>
+#include <sync/sync.h>
+
+using android::pdx::LocalHandle;
+
+namespace android {
+namespace dvr {
+
+AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+ LocalHandle acquire_fence, uint64_t /*sequence*/)
+ : buffer_(buffer), acquire_fence_(std::move(acquire_fence)) {}
+
+AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+ int* error) {
+ LocalHandle fence;
+ const int ret = buffer->Acquire(&fence);
+
+ if (error)
+ *error = ret;
+
+ if (ret < 0) {
+ ALOGW("AcquiredBuffer::AcquiredBuffer: Failed to acquire buffer: %s",
+ strerror(-ret));
+ buffer_ = nullptr;
+ // Default construct sets acquire_fence_ to empty.
+ } else {
+ buffer_ = buffer;
+ acquire_fence_ = std::move(fence);
+ }
+}
+
+AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other)
+ : buffer_(std::move(other.buffer_)),
+ acquire_fence_(std::move(other.acquire_fence_)) {}
+
+AcquiredBuffer::~AcquiredBuffer() { Release(LocalHandle(kEmptyFence)); }
+
+AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) {
+ if (this != &other) {
+ Release(LocalHandle(kEmptyFence));
+
+ buffer_ = std::move(other.buffer_);
+ acquire_fence_ = std::move(other.acquire_fence_);
+ }
+ return *this;
+}
+
+bool AcquiredBuffer::IsAvailable() const {
+ if (IsEmpty())
+ return false;
+
+ // Only check the fence if the acquire fence is not empty.
+ if (acquire_fence_) {
+ const int ret = sync_wait(acquire_fence_.Get(), 0);
+ ALOGD_IF(TRACE || (ret < 0 && errno != ETIME),
+ "AcquiredBuffer::IsAvailable: acquire_fence_=%d sync_wait()=%d "
+ "errno=%d.",
+ acquire_fence_.Get(), ret, ret < 0 ? errno : 0);
+ if (ret == 0) {
+ // The fence is completed, so to avoid further calls to sync_wait we close
+ // it here.
+ acquire_fence_.Close();
+ }
+ return ret == 0;
+ } else {
+ return true;
+ }
+}
+
+LocalHandle AcquiredBuffer::ClaimAcquireFence() {
+ return std::move(acquire_fence_);
+}
+
+std::shared_ptr<BufferConsumer> AcquiredBuffer::ClaimBuffer() {
+ return std::move(buffer_);
+}
+
+int AcquiredBuffer::Release(LocalHandle release_fence) {
+ if (buffer_) {
+ // Close the release fence since we can't transfer it with an async release.
+ release_fence.Close();
+ const int ret = buffer_->ReleaseAsync();
+ if (ret < 0) {
+ ALOGE("AcquiredBuffer::Release: Failed to release buffer %d: %s",
+ buffer_->id(), strerror(-ret));
+ if (ret != -ESHUTDOWN)
+ return ret;
+ }
+
+ buffer_ = nullptr;
+ acquire_fence_.Close();
+ }
+
+ return 0;
+}
+
+} // namespace dvr
+} // namespace android