bootmanager.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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 <QWindow>
  12. #include "common/thread.h"
  13. #include "core/core.h"
  14. #include "core/frontend/emu_window.h"
  15. class GRenderWindow;
  16. class QKeyEvent;
  17. class QScreen;
  18. class QTouchEvent;
  19. class QStringList;
  20. class QSurface;
  21. class QOpenGLContext;
  22. #ifdef HAS_VULKAN
  23. class QVulkanInstance;
  24. #endif
  25. namespace VideoCore {
  26. enum class LoadCallbackStage;
  27. }
  28. class EmuThread final : public QThread {
  29. Q_OBJECT
  30. public:
  31. explicit EmuThread(GRenderWindow& window);
  32. ~EmuThread() override;
  33. /**
  34. * Start emulation (on new thread)
  35. * @warning Only call when not running!
  36. */
  37. void run() override;
  38. /**
  39. * Steps the emulation thread by a single CPU instruction (if the CPU is not already running)
  40. * @note This function is thread-safe
  41. */
  42. void ExecStep() {
  43. exec_step = true;
  44. running_cv.notify_all();
  45. }
  46. /**
  47. * Sets whether the emulation thread is running or not
  48. * @param running Boolean value, set the emulation thread to running if true
  49. * @note This function is thread-safe
  50. */
  51. void SetRunning(bool running) {
  52. std::unique_lock lock{running_mutex};
  53. this->running = running;
  54. lock.unlock();
  55. running_cv.notify_all();
  56. }
  57. /**
  58. * Check if the emulation thread is running or not
  59. * @return True if the emulation thread is running, otherwise false
  60. * @note This function is thread-safe
  61. */
  62. bool IsRunning() const {
  63. return running;
  64. }
  65. /**
  66. * Requests for the emulation thread to stop running
  67. */
  68. void RequestStop() {
  69. stop_run = true;
  70. SetRunning(false);
  71. }
  72. private:
  73. bool exec_step = false;
  74. bool running = false;
  75. std::atomic_bool stop_run{false};
  76. std::mutex running_mutex;
  77. std::condition_variable running_cv;
  78. /// Only used in asynchronous GPU mode
  79. std::unique_ptr<Core::Frontend::GraphicsContext> shared_context;
  80. /// This is shared_context in asynchronous GPU mode, core_context in synchronous GPU mode
  81. Core::Frontend::GraphicsContext& context;
  82. signals:
  83. /**
  84. * Emitted when the CPU has halted execution
  85. *
  86. * @warning When connecting to this signal from other threads, make sure to specify either
  87. * Qt::QueuedConnection (invoke slot within the destination object's message thread) or even
  88. * Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
  89. */
  90. void DebugModeEntered();
  91. /**
  92. * Emitted right before the CPU continues execution
  93. *
  94. * @warning When connecting to this signal from other threads, make sure to specify either
  95. * Qt::QueuedConnection (invoke slot within the destination object's message thread) or even
  96. * Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
  97. */
  98. void DebugModeLeft();
  99. void ErrorThrown(Core::System::ResultStatus, std::string);
  100. void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
  101. };
  102. class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow {
  103. Q_OBJECT
  104. public:
  105. GRenderWindow(QWidget* parent, EmuThread* emu_thread);
  106. ~GRenderWindow() override;
  107. // EmuWindow implementation.
  108. void MakeCurrent() override;
  109. void DoneCurrent() override;
  110. void PollEvents() override;
  111. bool IsShown() const override;
  112. void RetrieveVulkanHandlers(void* get_instance_proc_addr, void* instance,
  113. void* surface) const override;
  114. std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override;
  115. void BackupGeometry();
  116. void RestoreGeometry();
  117. void restoreGeometry(const QByteArray& geometry); // overridden
  118. QByteArray saveGeometry(); // overridden
  119. qreal windowPixelRatio() const;
  120. void closeEvent(QCloseEvent* event) override;
  121. void resizeEvent(QResizeEvent* event) override;
  122. void keyPressEvent(QKeyEvent* event) override;
  123. void keyReleaseEvent(QKeyEvent* event) override;
  124. void mousePressEvent(QMouseEvent* event) override;
  125. void mouseMoveEvent(QMouseEvent* event) override;
  126. void mouseReleaseEvent(QMouseEvent* event) override;
  127. bool event(QEvent* event) override;
  128. void focusOutEvent(QFocusEvent* event) override;
  129. bool InitRenderTarget();
  130. /// Destroy the previous run's child_widget which should also destroy the child_window
  131. void ReleaseRenderTarget();
  132. void CaptureScreenshot(u32 res_scale, const QString& screenshot_path);
  133. public slots:
  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. std::pair<u32, u32> ScaleTouch(QPointF pos) const;
  143. void TouchBeginEvent(const QTouchEvent* event);
  144. void TouchUpdateEvent(const QTouchEvent* event);
  145. void TouchEndEvent();
  146. void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;
  147. bool InitializeOpenGL();
  148. bool InitializeVulkan();
  149. bool LoadOpenGL();
  150. QStringList GetUnsupportedGLExtensions() const;
  151. EmuThread* emu_thread;
  152. std::unique_ptr<GraphicsContext> core_context;
  153. #ifdef HAS_VULKAN
  154. std::unique_ptr<QVulkanInstance> vk_instance;
  155. #endif
  156. /// Temporary storage of the screenshot taken
  157. QImage screenshot_image;
  158. QByteArray geometry;
  159. /// Native window handle that backs this presentation widget
  160. QWindow* child_window = nullptr;
  161. /// In order to embed the window into GRenderWindow, you need to use createWindowContainer to
  162. /// put the child_window into a widget then add it to the layout. This child_widget can be
  163. /// parented to GRenderWindow and use Qt's lifetime system
  164. QWidget* child_widget = nullptr;
  165. bool first_frame = false;
  166. protected:
  167. void showEvent(QShowEvent* event) override;
  168. };