1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // SyncMtl:
7 //    Defines the class interface for SyncMtl, implementing SyncImpl.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_METAL_SYNCMTL_H_
11 #define LIBANGLE_RENDERER_METAL_SYNCMTL_H_
12 
13 #include <condition_variable>
14 #include <mutex>
15 
16 #include "libANGLE/renderer/EGLSyncImpl.h"
17 #include "libANGLE/renderer/FenceNVImpl.h"
18 #include "libANGLE/renderer/SyncImpl.h"
19 #include "libANGLE/renderer/metal/mtl_common.h"
20 
21 namespace egl
22 {
23 class AttributeMap;
24 }
25 
26 namespace rx
27 {
28 
29 class ContextMtl;
30 
31 namespace mtl
32 {
33 
34 // Common class to be used by both SyncImpl and EGLSyncImpl.
35 // NOTE: SharedEvent is only declared on iOS 12.0+ or mac 10.14+
36 #if ANGLE_MTL_EVENT_AVAILABLE
37 class Sync
38 {
39   public:
40     Sync();
41     ~Sync();
42 
43     void onDestroy();
44 
45     angle::Result initialize(ContextMtl *contextMtl);
46 
47     angle::Result set(ContextMtl *contextMtl, GLenum condition, GLbitfield flags);
48     angle::Result clientWait(ContextMtl *contextMtl,
49                              bool flushCommands,
50                              uint64_t timeout,
51                              GLenum *outResult);
52     void serverWait(ContextMtl *contextMtl);
53     angle::Result getStatus(bool *signaled);
54 
55   private:
56     SharedEventRef mMetalSharedEvent;
57     uint64_t mSetCounter = 0;
58 
59     std::shared_ptr<std::condition_variable> mCv;
60     std::shared_ptr<std::mutex> mLock;
61 };
62 #else   // #if ANGLE_MTL_EVENT_AVAILABLE
63 class Sync
64 {
65   public:
66     void onDestroy() { UNREACHABLE(); }
67 
68     angle::Result initialize(ContextMtl *context)
69     {
70         UNREACHABLE();
71         return angle::Result::Stop;
72     }
73     angle::Result set(ContextMtl *contextMtl, GLenum condition, GLbitfield flags)
74     {
75         UNREACHABLE();
76         return angle::Result::Stop;
77     }
78     angle::Result clientWait(ContextMtl *context,
79                              bool flushCommands,
80                              uint64_t timeout,
81                              GLenum *outResult)
82     {
83         UNREACHABLE();
84         return angle::Result::Stop;
85     }
86     void serverWait(ContextMtl *contextMtl) { UNREACHABLE(); }
87     angle::Result getStatus(bool *signaled)
88     {
89         UNREACHABLE();
90         return angle::Result::Stop;
91     }
92 };
93 #endif  // #if ANGLE_MTL_EVENT_AVAILABLE
94 }  // namespace mtl
95 
96 class FenceNVMtl : public FenceNVImpl
97 {
98   public:
99     FenceNVMtl();
100     ~FenceNVMtl() override;
101 
102     void onDestroy(const gl::Context *context) override;
103 
104     angle::Result set(const gl::Context *context, GLenum condition) override;
105     angle::Result test(const gl::Context *context, GLboolean *outFinished) override;
106     angle::Result finish(const gl::Context *context) override;
107 
108   private:
109     mtl::Sync mSync;
110 };
111 
112 class SyncMtl : public SyncImpl
113 {
114   public:
115     SyncMtl();
116     ~SyncMtl() override;
117 
118     void onDestroy(const gl::Context *context) override;
119 
120     angle::Result set(const gl::Context *context, GLenum condition, GLbitfield flags) override;
121     angle::Result clientWait(const gl::Context *context,
122                              GLbitfield flags,
123                              GLuint64 timeout,
124                              GLenum *outResult) override;
125     angle::Result serverWait(const gl::Context *context,
126                              GLbitfield flags,
127                              GLuint64 timeout) override;
128     angle::Result getStatus(const gl::Context *context, GLint *outResult) override;
129 
130   private:
131     mtl::Sync mSync;
132 };
133 
134 class EGLSyncMtl final : public EGLSyncImpl
135 {
136   public:
137     EGLSyncMtl(const egl::AttributeMap &attribs);
138     ~EGLSyncMtl() override;
139 
140     void onDestroy(const egl::Display *display) override;
141 
142     egl::Error initialize(const egl::Display *display,
143                           const gl::Context *context,
144                           EGLenum type) override;
145     egl::Error clientWait(const egl::Display *display,
146                           const gl::Context *context,
147                           EGLint flags,
148                           EGLTime timeout,
149                           EGLint *outResult) override;
150     egl::Error serverWait(const egl::Display *display,
151                           const gl::Context *context,
152                           EGLint flags) override;
153     egl::Error getStatus(const egl::Display *display, EGLint *outStatus) override;
154 
155   private:
156     mtl::Sync mSync;
157 };
158 
159 }  // namespace rx
160 
161 #endif
162