1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "client.h"
6 #include "fence.h"
7
8 #include <utility>
9
10 namespace display {
11
CreateRef()12 bool Fence::CreateRef() {
13 fbl::AllocChecker ac;
14 cur_ref_ = fbl::AdoptRef(new (&ac) FenceReference(fbl::RefPtr<Fence>(this)));
15 if (ac.check()) {
16 ref_count_++;
17 }
18
19 return ac.check();
20 }
21
ClearRef()22 void Fence::ClearRef() {
23 cur_ref_ = nullptr;
24 }
25
GetReference()26 fbl::RefPtr<FenceReference> Fence::GetReference() {
27 return cur_ref_;
28 }
29
Signal()30 void Fence::Signal() {
31 event_.signal(0, ZX_EVENT_SIGNALED);
32 }
33
OnRefDead()34 bool Fence::OnRefDead() {
35 return --ref_count_ == 0;
36 }
37
OnRefArmed(fbl::RefPtr<FenceReference> && ref)38 zx_status_t Fence::OnRefArmed(fbl::RefPtr<FenceReference>&& ref) {
39 if (armed_refs_.is_empty()) {
40 ready_wait_.set_object(event_.get());
41 ready_wait_.set_trigger(ZX_EVENT_SIGNALED);
42
43 zx_status_t status = ready_wait_.Begin(dispatcher_);
44 if (status != ZX_OK) {
45 return status;
46 }
47 }
48
49 armed_refs_.push_back(std::move(ref));
50 return ZX_OK;
51 }
52
OnRefDisarmed(FenceReference * ref)53 void Fence::OnRefDisarmed(FenceReference* ref) {
54 armed_refs_.erase(*ref);
55 if (armed_refs_.is_empty()) {
56 ready_wait_.Cancel();
57 }
58 }
59
OnReady(async_dispatcher_t * dispatcher,async::WaitBase * self,zx_status_t status,const zx_packet_signal_t * signal)60 void Fence::OnReady(async_dispatcher_t* dispatcher, async::WaitBase* self,
61 zx_status_t status, const zx_packet_signal_t* signal) {
62 ZX_DEBUG_ASSERT(status == ZX_OK && (signal->observed & ZX_EVENT_SIGNALED));
63
64 event_.signal(ZX_EVENT_SIGNALED, 0);
65
66 fbl::RefPtr<FenceReference> ref = armed_refs_.pop_front();
67 ref->OnReady();
68 cb_->OnFenceFired(ref.get());
69
70 if (!armed_refs_.is_empty()) {
71 ready_wait_.Begin(dispatcher_);
72 }
73 }
74
Fence(FenceCallback * cb,async_dispatcher_t * dispatcher,uint64_t fence_id,zx::event && event)75 Fence::Fence(FenceCallback* cb, async_dispatcher_t* dispatcher, uint64_t fence_id, zx::event&& event)
76 : cb_(cb), dispatcher_(dispatcher), event_(std::move(event)) {
77 id = fence_id;
78 }
79
~Fence()80 Fence::~Fence() {
81 ZX_DEBUG_ASSERT(armed_refs_.is_empty());
82 ZX_DEBUG_ASSERT(ref_count_ == 0);
83 }
84
StartReadyWait()85 zx_status_t FenceReference::StartReadyWait() {
86 return fence_->OnRefArmed(fbl::RefPtr<FenceReference>(this));
87 }
88
ResetReadyWait()89 void FenceReference::ResetReadyWait() {
90 fence_->OnRefDisarmed(this);
91 }
92
SetImmediateRelease(fbl::RefPtr<FenceReference> && fence)93 void FenceReference::SetImmediateRelease(fbl::RefPtr<FenceReference>&& fence) {
94 release_fence_ = std::move(fence);
95 }
96
OnReady()97 void FenceReference::OnReady() {
98 if (release_fence_) {
99 release_fence_->Signal();
100 release_fence_ = nullptr;
101 }
102 }
103
Signal()104 void FenceReference::Signal() {
105 fence_->Signal();
106 }
107
FenceReference(fbl::RefPtr<Fence> fence)108 FenceReference::FenceReference(fbl::RefPtr<Fence> fence) : fence_(std::move(fence)) { }
109
~FenceReference()110 FenceReference::~FenceReference() {
111 fence_->cb_->OnRefForFenceDead(fence_.get());
112 }
113
114 } // namespace display
115