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 #if GFXSTREAM_ENABLE_HOST_GLES 20 #include <EGL/egl.h> 21 #include <GLES2/gl2.h> 22 #include <GLES2/gl2ext.h> 23 24 #include "gl/EmulatedEglFenceSync.h" 25 #endif 26 27 #include <functional> 28 #include <future> 29 #include <string> 30 #include <type_traits> 31 32 #include "aemu/base/HealthMonitor.h" 33 #include "aemu/base/Optional.h" 34 #include "aemu/base/synchronization/ConditionVariable.h" 35 #include "aemu/base/synchronization/Lock.h" 36 #include "aemu/base/synchronization/MessageChannel.h" 37 #include "aemu/base/threads/Thread.h" 38 #include "aemu/base/threads/ThreadPool.h" 39 #include "render-utils/virtio_gpu_ops.h" 40 #include "vulkan/VkDecoderGlobalState.h" 41 42 namespace gfxstream { 43 44 using emugl::HealthMonitor; 45 using emugl::HealthWatchdog; 46 47 // SyncThread/////////////////////////////////////////////////////////////////// 48 // The purpose of SyncThread is to track sync device timelines and give out + 49 // signal FD's that correspond to the completion of host-side GL fence commands. 50 51 struct RenderThreadInfo; 52 class SyncThread : public android::base::Thread { 53 public: 54 // - constructor: start up the sync worker threads for a given context. 55 // The initialization of the sync threads is nonblocking. 56 // - Triggers a |SyncThreadCmd| with op code |SYNC_THREAD_EGL_INIT| 57 SyncThread(bool hasGl, HealthMonitor<>* healthMonitor); 58 ~SyncThread(); 59 60 // |triggerWaitVk|: async wait with a given VkFence object. 61 // The |vkFence| argument is a *boxed* host Vulkan handle of the fence. 62 // 63 // We call vkWaitForFences() on host Vulkan device to wait for the fence. 64 // After wait is over, the timeline will be incremented, 65 // which should signal the guest-side fence FD / Zircon eventpair. 66 // This method is how the goldfish sync virtual device 67 // knows when to increment timelines / signal native fence FD's. 68 void triggerWaitVk(VkFence vkFence, uint64_t timeline); 69 70 #if GFXSTREAM_ENABLE_HOST_GLES 71 // |triggerWait|: async wait with a given EmulatedEglFenceSync object. 72 // We use the wait() method to do a eglClientWaitSyncKHR. 73 // After wait is over, the timeline will be incremented, 74 // which should signal the guest-side fence FD. 75 // This method is how the goldfish sync virtual device 76 // knows when to increment timelines / signal native fence FD's. 77 void triggerWait(gl::EmulatedEglFenceSync* fenceSync, uint64_t timeline); 78 79 // for use with the virtio-gpu path; is meant to have a current context 80 // while waiting. 81 void triggerBlockedWaitNoTimeline(gl::EmulatedEglFenceSync* fenceSync); 82 83 // For use with virtio-gpu and async fence completion callback. This is async like triggerWait, 84 // but takes a fence completion callback instead of incrementing some timeline directly. 85 void triggerWaitWithCompletionCallback(gl::EmulatedEglFenceSync* fenceSync, 86 FenceCompletionCallback); 87 88 // |initSyncContext| creates an EGL context expressly for calling 89 // eglClientWaitSyncKHR in the processing caused by |triggerWait|. 90 // This is used by the constructor only. It is non-blocking. 91 // - Triggers a |SyncThreadCmd| with op code |SYNC_THREAD_EGL_INIT| 92 void initSyncEGLContext(); 93 94 void doSyncWait(gl::EmulatedEglFenceSync* fenceSync, std::function<void()> onComplete); 95 #endif 96 97 // This increments the timeline after the QSRI completes. 98 void triggerWaitVkQsri(VkImage vkImage, uint64_t timeline); 99 100 void triggerWaitVkWithCompletionCallback(VkFence fenceHandle, FenceCompletionCallback); 101 void triggerWaitVkQsriWithCompletionCallback(VkImage image, FenceCompletionCallback); 102 void triggerGeneral(FenceCompletionCallback, std::string description); 103 104 // |cleanup|: for use with destructors and other cleanup functions. 105 // it destroys the sync context and exits the sync thread. 106 // This is blocking; after this function returns, we're sure 107 // the sync thread is gone. 108 // - Triggers a |SyncThreadCmd| with op code |SYNC_THREAD_EXIT| 109 void cleanup(); 110 111 // Initialize the global sync thread. 112 static void initialize(bool hasGl, HealthMonitor<>* healthMonitor); 113 114 // Obtains the global sync thread. 115 static SyncThread* get(); 116 117 // Destroys and cleanup the global sync thread. 118 static void destroy(); 119 120 private: 121 using WorkerId = android::base::ThreadPoolWorkerId; 122 struct Command { 123 std::packaged_task<int(WorkerId)> mTask; 124 std::string mDescription; 125 }; 126 using ThreadPool = android::base::ThreadPool<Command>; 127 128 // Thread function. 129 // It keeps the workers runner until |mExiting| is set. 130 virtual intptr_t main() override final; 131 132 // These two functions are used to communicate with the sync thread from another thread: 133 // - |sendAndWaitForResult| issues |job| to the sync thread, and blocks until it receives the 134 // result of the job. 135 // - |sendAsync| issues |job| to the sync thread and does not wait for the result, returning 136 // immediately after. 137 int sendAndWaitForResult(std::function<int(WorkerId)> job, std::string description); 138 void sendAsync(std::function<void(WorkerId)> job, std::string description); 139 140 // |doSyncThreadCmd| execute the actual task. These run on the sync thread. 141 void doSyncThreadCmd(Command&& command, ThreadPool::WorkerId); 142 143 static int doSyncWaitVk(VkFence, std::function<void()> onComplete); 144 145 // EGL objects / object handles specific to 146 // a sync thread. 147 static const uint32_t kNumWorkerThreads = 4u; 148 149 #if GFXSTREAM_ENABLE_HOST_GLES 150 EGLDisplay mDisplay = EGL_NO_DISPLAY; 151 EGLSurface mSurface[kNumWorkerThreads]; 152 EGLContext mContext[kNumWorkerThreads]; 153 #endif 154 155 bool mExiting = false; 156 android::base::Lock mLock; 157 android::base::ConditionVariable mCv; 158 ThreadPool mWorkerThreadPool; 159 bool mHasGl; 160 161 HealthMonitor<>* mHealthMonitor; 162 }; 163 164 } // namespace gfxstream 165