bootmanager.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <atomic>
  6. #include <condition_variable>
  7. #include <mutex>
  8. #include <QImage>
  9. #include <QThread>
  10. #include <QWidget>
  11. #include "common/thread.h"
  12. #include "core/core.h"
  13. #include "core/frontend/emu_window.h"
  14. class QKeyEvent;
  15. class QScreen;
  16. class QTouchEvent;
  17. class QStringList;
  18. class QSurface;
  19. class QOpenGLContext;
  20. #ifdef HAS_VULKAN
  21. class QVulkanInstance;
  22. #endif
  23. class GWidgetInternal;
  24. class GGLWidgetInternal;
  25. class GVKWidgetInternal;
  26. class GMainWindow;
  27. class GRenderWindow;
  28. class QSurface;
  29. class QOpenGLContext;
  30. namespace VideoCore {
  31. enum class LoadCallbackStage;
  32. }
  33. class EmuThread final : public QThread {
  34. Q_OBJECT
  35. public:
  36. explicit EmuThread(GRenderWindow* render_window);
  37. ~EmuThread() override;
  38. /**
  39. * Start emulation (on new thread)
  40. * @warning Only call when not running!
  41. */
  42. void run() override;
  43. /**
  44. * Steps the emulation thread by a single CPU instruction (if the CPU is not already running)
  45. * @note This function is thread-safe
  46. */
  47. void ExecStep() {
  48. exec_step = true;
  49. running_cv.notify_all();
  50. }
  51. /**
  52. * Sets whether the emulation thread is running or not
  53. * @param running Boolean value, set the emulation thread to running if true
  54. * @note This function is thread-safe
  55. */
  56. void SetRunning(bool running) {
  57. std::unique_lock lock{running_mutex};
  58. this->running = running;
  59. lock.unlock();
  60. running_cv.notify_all();
  61. }
  62. /**
  63. * Check if the emulation thread is running or not
  64. * @return True if the emulation thread is running, otherwise false
  65. * @note This function is thread-safe
  66. */
  67. bool IsRunning() const {
  68. return running;
  69. }
  70. /**
  71. * Requests for the emulation thread to stop running
  72. */
  73. void RequestStop() {
  74. stop_run = true;
  75. SetRunning(false);
  76. }
  77. private:
  78. bool exec_step = false;
  79. bool running = false;
  80. std::atomic_bool stop_run{false};
  81. std::mutex running_mutex;
  82. std::condition_variable running_cv;
  83. GRenderWindow* render_window;
  84. signals:
  85. /**
  86. * Emitted when the CPU has halted execution
  87. *
  88. * @warning When connecting to this signal from other threads, make sure to specify either
  89. * Qt::QueuedConnection (invoke slot within the destination object's message thread) or even
  90. * Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
  91. */
  92. void DebugModeEntered();
  93. /**
  94. * Emitted right before the CPU continues execution
  95. *
  96. * @warning When connecting to this signal from other threads, make sure to specify either
  97. * Qt::QueuedConnection (invoke slot within the destination object's message thread) or even
  98. * Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
  99. */
  100. void DebugModeLeft();
  101. void ErrorThrown(Core::System::ResultStatus, std::string);
  102. void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
  103. };
  104. class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow {
  105. Q_OBJECT
  106. public:
  107. GRenderWindow(GMainWindow* parent, EmuThread* emu_thread);
  108. ~GRenderWindow() override;
  109. // EmuWindow implementation
  110. void SwapBuffers() override;
  111. void MakeCurrent() override;
  112. void DoneCurrent() override;
  113. void PollEvents() override;
  114. bool IsShown() const override;
  115. void RetrieveVulkanHandlers(void* get_instance_proc_addr, void* instance,
  116. void* surface) const override;
  117. std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override;
  118. void ForwardKeyPressEvent(QKeyEvent* event);
  119. void ForwardKeyReleaseEvent(QKeyEvent* event);
  120. void BackupGeometry();
  121. void RestoreGeometry();
  122. void restoreGeometry(const QByteArray& geometry); // overridden
  123. QByteArray saveGeometry(); // overridden
  124. qreal GetWindowPixelRatio() const;
  125. std::pair<u32, u32> ScaleTouch(QPointF pos) const;
  126. void closeEvent(QCloseEvent* event) override;
  127. bool event(QEvent* event) override;
  128. void focusOutEvent(QFocusEvent* event) override;
  129. void OnClientAreaResized(u32 width, u32 height);
  130. bool InitRenderTarget();
  131. void CaptureScreenshot(u32 res_scale, const QString& screenshot_path);
  132. public slots:
  133. void moveContext(); // overridden
  134. void OnEmulationStarting(EmuThread* emu_thread);
  135. void OnEmulationStopping();
  136. void OnFramebufferSizeChanged();
  137. signals:
  138. /// Emitted when the window is closed
  139. void Closed();
  140. void FirstFrameDisplayed();
  141. private:
  142. void TouchBeginEvent(const QTouchEvent* event);
  143. void TouchUpdateEvent(const QTouchEvent* event);
  144. void TouchEndEvent();
  145. void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;
  146. bool InitializeOpenGL();
  147. bool InitializeVulkan();
  148. bool LoadOpenGL();
  149. QStringList GetUnsupportedGLExtensions() const;
  150. QWidget* container = nullptr;
  151. GWidgetInternal* child = nullptr;
  152. EmuThread* emu_thread;
  153. // Context that backs the GGLWidgetInternal (and will be used by core to render)
  154. std::unique_ptr<QOpenGLContext> context;
  155. // Context that will be shared between all newly created contexts. This should never be made
  156. // current
  157. std::unique_ptr<QOpenGLContext> shared_context;
  158. #ifdef HAS_VULKAN
  159. std::unique_ptr<QVulkanInstance> vk_instance;
  160. #endif
  161. /// Temporary storage of the screenshot taken
  162. QImage screenshot_image;
  163. QByteArray geometry;
  164. bool first_frame = false;
  165. protected:
  166. void showEvent(QShowEvent* event) override;
  167. };