Automation.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #include "il2cpp-config.h"
  2. #include "il2cpp-api.h"
  3. #if IL2CPP_TARGET_LUMIN && IL2CPP_TARGET_LUMIN_AUTOMATION
  4. #include "Automation.h"
  5. #include <atomic>
  6. #include <chrono>
  7. #include <thread>
  8. #ifndef EGL_EGLEXT_PROTOTYPES
  9. #define EGL_EGLEXT_PROTOTYPES
  10. #endif
  11. #include <EGL/egl.h>
  12. #include <EGL/eglext.h>
  13. #ifndef GL_GLEXT_PROTOTYPES
  14. #define GL_GLEXT_PROTOTYPES
  15. #endif
  16. #include <GLES3/gl3.h>
  17. #include <GLES3/gl3ext.h>
  18. #define ML_DEFAULT_LOG_TAG "il2cpp"
  19. #include "ml_graphics.h"
  20. #include "ml_head_tracking.h"
  21. #include "ml_lifecycle.h"
  22. #include "ml_logging.h"
  23. #include "ml_perception.h"
  24. static void onStopWrapper(void* app_ctx);
  25. static void onPauseWrapper(void *app_ctx);
  26. static void onResumeWrapper(void *app_ctx);
  27. static std::thread s_app_thread;
  28. namespace il2cpp
  29. {
  30. namespace os
  31. {
  32. namespace lumin
  33. {
  34. namespace automation
  35. {
  36. class app_ctx_t;
  37. static app_ctx_t* s_app;
  38. class app_ctx_t
  39. {
  40. public:
  41. app_ctx_t();
  42. ~app_ctx_t();
  43. bool init();
  44. void main_loop();
  45. void on_stop();
  46. void on_pause();
  47. void on_resume();
  48. void makeCurrent();
  49. void releaseCurrent();
  50. private:
  51. EGLContext context;
  52. EGLDisplay display;
  53. MLHandle graphics_client;
  54. std::atomic_int op_mode;
  55. };
  56. app_ctx_t::app_ctx_t() :
  57. graphics_client(ML_INVALID_HANDLE),
  58. op_mode(0)
  59. {
  60. display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  61. eglInitialize(display, nullptr, nullptr);
  62. eglBindAPI(EGL_OPENGL_ES_API);
  63. EGLint config_attribs[] = {
  64. EGL_RED_SIZE, 5,
  65. EGL_GREEN_SIZE, 6,
  66. EGL_BLUE_SIZE, 5,
  67. EGL_ALPHA_SIZE, 0,
  68. EGL_DEPTH_SIZE, 24,
  69. EGL_STENCIL_SIZE, 8,
  70. EGL_NONE
  71. };
  72. EGLConfig egl_config = nullptr;
  73. EGLint config_size = 0;
  74. eglChooseConfig(display, config_attribs, &egl_config, 1, &config_size);
  75. EGLint context_attribs[] = {
  76. EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
  77. EGL_CONTEXT_MINOR_VERSION_KHR, 0,
  78. EGL_NONE
  79. };
  80. context = eglCreateContext(display, egl_config, EGL_NO_CONTEXT, context_attribs);
  81. }
  82. app_ctx_t::~app_ctx_t()
  83. {
  84. eglDestroyContext(display, context);
  85. eglTerminate(display);
  86. }
  87. bool app_ctx_t::init()
  88. {
  89. MLLifecycleCallbacks cbs = {0};
  90. cbs.on_stop = &onStopWrapper;
  91. cbs.on_pause = &onPauseWrapper;
  92. cbs.on_resume = &onResumeWrapper;
  93. if (MLLifecycleInit(&cbs, static_cast<void*>(this)) != MLResult_Ok)
  94. {
  95. ML_LOG(Error, "[il2cpp_automation]: failed to initialize lifecycle");
  96. return false;
  97. }
  98. // initialize perception system
  99. MLPerceptionSettings perception_settings;
  100. if (MLResult_Ok != MLPerceptionInitSettings(&perception_settings))
  101. {
  102. ML_LOG(Error, "[il2cpp_automation]: Failed to initialize perception.");
  103. }
  104. if (MLResult_Ok != MLPerceptionStartup(&perception_settings))
  105. {
  106. ML_LOG(Error, "[il2cpp_automation]: Failed to startup perception.");
  107. return false;
  108. }
  109. return true;
  110. }
  111. void app_ctx_t::main_loop()
  112. {
  113. on_resume();
  114. makeCurrent();
  115. // Get ready to connect our GL context to the MLSDK graphics API
  116. MLGraphicsOptions graphics_options = { 0, MLSurfaceFormat_RGBA8UNorm, MLSurfaceFormat_D32Float };
  117. MLHandle opengl_context = reinterpret_cast<MLHandle>(context);
  118. MLGraphicsCreateClientGL(&graphics_options, opengl_context, &graphics_client);
  119. GLuint framebuffer_id;
  120. glGenFramebuffers(1, &framebuffer_id);
  121. MLHandle head_tracker;
  122. MLResult head_track_result = MLHeadTrackingCreate(&head_tracker);
  123. MLHeadTrackingStaticData head_static_data;
  124. if (MLResult_Ok == head_track_result && MLHandleIsValid(head_tracker))
  125. {
  126. MLHeadTrackingGetStaticData(head_tracker, &head_static_data);
  127. }
  128. else
  129. {
  130. ML_LOG(Error, "[il2cpp_automation]: Failed to create head tracker.");
  131. }
  132. ML_LOG(Info, "[il2cpp_automation]: Start loop.");
  133. auto start = std::chrono::steady_clock::now();
  134. do
  135. {
  136. MLGraphicsFrameParams frame_params;
  137. MLResult out_result = MLGraphicsInitFrameParams(&frame_params);
  138. if (MLResult_Ok != out_result)
  139. {
  140. ML_LOG(Error, "MLGraphicsInitFrameParams complained: %d", out_result);
  141. }
  142. frame_params.surface_scale = 1.0f;
  143. frame_params.far_clip = 100.0f;
  144. frame_params.near_clip = 0.37f;
  145. frame_params.focus_distance = 100.0f;
  146. MLHandle frame_handle = ML_INVALID_HANDLE;
  147. MLGraphicsVirtualCameraInfoArray virtual_camera_array;
  148. out_result = MLGraphicsBeginFrame(graphics_client, &frame_params, &frame_handle, &virtual_camera_array);
  149. if (MLResult_Ok != out_result)
  150. {
  151. static bool loggedBeginFrameFailure = false;
  152. if (!loggedBeginFrameFailure)
  153. {
  154. ML_LOG(Error, "MLGraphicsInitFrameParams complained: %d", out_result);
  155. loggedBeginFrameFailure = true;
  156. }
  157. if (((int)op_mode) > 0)
  158. continue; // early out if we fail to acquire a frame.
  159. else
  160. break;
  161. }
  162. auto msRuntime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count();
  163. auto factor = labs(msRuntime % 2000 - 1000) / 1000.0;
  164. for (int camera = 0; camera < 2; ++camera)
  165. {
  166. glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id);
  167. glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, virtual_camera_array.color_id, 0, camera);
  168. glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, virtual_camera_array.depth_id, 0, camera);
  169. const MLRectf& viewport = virtual_camera_array.viewport;
  170. glViewport((GLint)viewport.x, (GLint)viewport.y,
  171. (GLsizei)viewport.w, (GLsizei)viewport.h);
  172. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  173. if (camera == 0)
  174. {
  175. glClearColor(1.0 - factor, 0.0, 0.0, 0.0);
  176. }
  177. else
  178. {
  179. glClearColor(0.0, 0.0, factor, 0.0);
  180. }
  181. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  182. MLGraphicsSignalSyncObjectGL(graphics_client, virtual_camera_array.virtual_cameras[camera].sync_object);
  183. }
  184. out_result = MLGraphicsEndFrame(graphics_client, frame_handle);
  185. if (MLResult_Ok != out_result)
  186. {
  187. ML_LOG(Error, "MLGraphicsEndFrame complained: %d", out_result);
  188. }
  189. }
  190. while (((int)op_mode) > 0);
  191. ML_LOG(Info, "[il2cpp_automation]: End loop.");
  192. glDeleteFramebuffers(1, &framebuffer_id);
  193. releaseCurrent();
  194. // clean up system
  195. MLGraphicsDestroyClient(&graphics_client);
  196. MLPerceptionShutdown();
  197. }
  198. void app_ctx_t::on_stop()
  199. {
  200. op_mode = 0;
  201. }
  202. void app_ctx_t::on_pause()
  203. {
  204. op_mode = 1;
  205. }
  206. void app_ctx_t::on_resume()
  207. {
  208. op_mode = 2;
  209. }
  210. void app_ctx_t::makeCurrent()
  211. {
  212. eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
  213. }
  214. void app_ctx_t::releaseCurrent()
  215. {
  216. eglMakeCurrent(NULL, EGL_NO_SURFACE, EGL_NO_SURFACE, NULL);
  217. }
  218. void Bootstrap()
  219. {
  220. il2cpp_set_data_dir("/package/Data");
  221. il2cpp_set_config_dir("/package/Data/etc");
  222. s_app = new app_ctx_t;
  223. if (s_app->init())
  224. {
  225. s_app_thread = std::thread(&app_ctx_t::main_loop, s_app);
  226. }
  227. MLLifecycleSetReadyIndication();
  228. }
  229. void WaitForAppThread()
  230. {
  231. if (s_app)
  232. s_app->on_stop();
  233. if (s_app_thread.joinable())
  234. s_app_thread.join();
  235. delete s_app;
  236. s_app = nullptr;
  237. }
  238. }
  239. }
  240. }
  241. }
  242. static void onStopWrapper(void* app_ctx)
  243. {
  244. auto ctx = static_cast<il2cpp::os::lumin::automation::app_ctx_t*>(app_ctx);
  245. ctx->on_stop();
  246. }
  247. static void onPauseWrapper(void *app_ctx)
  248. {
  249. auto ctx = static_cast<il2cpp::os::lumin::automation::app_ctx_t*>(app_ctx);
  250. ctx->on_pause();
  251. }
  252. static void onResumeWrapper(void *app_ctx)
  253. {
  254. auto ctx = static_cast<il2cpp::os::lumin::automation::app_ctx_t*>(app_ctx);
  255. ctx->on_resume();
  256. }
  257. #endif //IL2CPP_TARGET_LUMIN_AUTOMATION