• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 #pragma once
18 
19 #include <EGL/egl.h>
20 #include <GLES2/gl2.h>
21 #include <GLES2/gl2ext.h>
22 
23 #include <functional>
24 #include <future>
25 #include <string>
26 #include <type_traits>
27 
28 #include "FenceSync.h"
29 #include "base/ConditionVariable.h"
30 #include "base/Lock.h"
31 #include "base/MessageChannel.h"
32 #include "base/Optional.h"
33 #include "base/Thread.h"
34 #include "base/ThreadPool.h"
35 #include "virtio_gpu_ops.h"
36 #include "vulkan/VkDecoderGlobalState.h"
37 
38 // SyncThread///////////////////////////////////////////////////////////////////
39 // The purpose of SyncThread is to track sync device timelines and give out +
40 // signal FD's that correspond to the completion of host-side GL fence commands.
41 
42 
43 struct RenderThreadInfo;
44 class SyncThread : public android::base::Thread {
45 public:
46     // - constructor: start up the sync worker threads for a given context.
47     // The initialization of the sync threads is nonblocking.
48     // - Triggers a |SyncThreadCmd| with op code |SYNC_THREAD_EGL_INIT|
49     SyncThread(bool noGL);
50     ~SyncThread();
51 
52     // |triggerWait|: async wait with a given FenceSync object.
53     // We use the wait() method to do a eglClientWaitSyncKHR.
54     // After wait is over, the timeline will be incremented,
55     // which should signal the guest-side fence FD.
56     // This method is how the goldfish sync virtual device
57     // knows when to increment timelines / signal native fence FD's.
58     void triggerWait(FenceSync* fenceSync,
59                      uint64_t timeline);
60 
61     // |triggerWaitVk|: async wait with a given VkFence object.
62     // The |vkFence| argument is a *boxed* host Vulkan handle of the fence.
63     //
64     // We call vkWaitForFences() on host Vulkan device to wait for the fence.
65     // After wait is over, the timeline will be incremented,
66     // which should signal the guest-side fence FD / Zircon eventpair.
67     // This method is how the goldfish sync virtual device
68     // knows when to increment timelines / signal native fence FD's.
69     void triggerWaitVk(VkFence vkFence, uint64_t timeline);
70 
71     // for use with the virtio-gpu path; is meant to have a current context
72     // while waiting.
73     void triggerBlockedWaitNoTimeline(FenceSync* fenceSync);
74 
75     // For use with virtio-gpu and async fence completion callback. This is async like triggerWait, but takes a fence completion callback instead of incrementing some timeline directly.
76     void triggerWaitWithCompletionCallback(FenceSync* fenceSync, FenceCompletionCallback);
77     void triggerWaitVkWithCompletionCallback(VkFence fenceHandle, FenceCompletionCallback);
78     void triggerWaitVkQsriWithCompletionCallback(VkImage image, FenceCompletionCallback);
79     void triggerGeneral(FenceCompletionCallback, std::string description);
80 
81     // |cleanup|: for use with destructors and other cleanup functions.
82     // it destroys the sync context and exits the sync thread.
83     // This is blocking; after this function returns, we're sure
84     // the sync thread is gone.
85     // - Triggers a |SyncThreadCmd| with op code |SYNC_THREAD_EXIT|
86     void cleanup();
87 
88     // Initialize the global sync thread.
89     static void initialize(bool noGL);
90 
91     // Obtains the global sync thread.
92     static SyncThread* get();
93 
94     // Destroys and cleanup the global sync thread.
95     static void destroy();
96 
97    private:
98     using WorkerId = android::base::ThreadPoolWorkerId;
99     struct Command {
100         std::packaged_task<int(WorkerId)> mTask;
101         std::string mDescription;
102     };
103     using ThreadPool = android::base::ThreadPool<Command>;
104 
105     // |initSyncContext| creates an EGL context expressly for calling
106     // eglClientWaitSyncKHR in the processing caused by |triggerWait|.
107     // This is used by the constructor only. It is non-blocking.
108     // - Triggers a |SyncThreadCmd| with op code |SYNC_THREAD_EGL_INIT|
109     void initSyncEGLContext();
110 
111     // Thread function.
112     // It keeps the workers runner until |mExiting| is set.
113     virtual intptr_t main() override final;
114 
115     // These two functions are used to communicate with the sync thread from another thread:
116     // - |sendAndWaitForResult| issues |job| to the sync thread, and blocks until it receives the
117     // result of the job.
118     // - |sendAsync| issues |job| to the sync thread and does not wait for the result, returning
119     // immediately after.
120     int sendAndWaitForResult(std::function<int(WorkerId)> job, std::string description);
121     void sendAsync(std::function<void(WorkerId)> job, std::string description);
122 
123     // |doSyncThreadCmd| execute the actual task. These run on the sync thread.
124     static void doSyncThreadCmd(Command&& command, ThreadPool::WorkerId);
125 
126     void doSyncWait(FenceSync* fenceSync, std::function<void()> onComplete);
127     static int doSyncWaitVk(VkFence, std::function<void()> onComplete);
128 
129     // EGL objects / object handles specific to
130     // a sync thread.
131     static const uint32_t kNumWorkerThreads = 4u;
132 
133     EGLDisplay mDisplay = EGL_NO_DISPLAY;
134     EGLSurface mSurface[kNumWorkerThreads];
135     EGLContext mContext[kNumWorkerThreads];
136 
137     bool mExiting = false;
138     android::base::Lock mLock;
139     android::base::ConditionVariable mCv;
140     ThreadPool mWorkerThreadPool;
141     bool mNoGL;
142 };
143 
144