2015-01-04 09:36:57 -08:00
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
2014-10-12 18:14:57 +02:00
# include <atomic>
2015-05-16 11:56:00 -06:00
# include <condition_variable>
# include <mutex>
2014-10-12 18:14:57 +02:00
2014-03-31 22:26:50 -04:00
# include <QGLWidget>
2015-09-11 00:23:00 -04:00
# include <QThread>
2014-10-12 18:14:57 +02:00
2014-04-10 20:50:10 -04:00
# include "common/emu_window.h"
2015-04-16 23:31:14 -04:00
# include "common/thread.h"
2014-03-31 22:26:50 -04:00
class QKeyEvent ;
2015-08-26 22:04:12 +02:00
class QScreen ;
2014-03-31 22:26:50 -04:00
2015-08-26 22:04:12 +02:00
class GGLWidgetInternal ;
2015-04-16 18:35:09 -04:00
class GMainWindow ;
2015-08-26 22:04:12 +02:00
class GRenderWindow ;
2014-10-12 18:14:57 +02:00
2014-03-31 22:26:50 -04:00
class EmuThread : public QThread
{
Q_OBJECT
public :
2015-04-29 00:01:41 -04:00
EmuThread ( GRenderWindow * render_window ) ;
2014-03-31 22:26:50 -04:00
/**
* Start emulation (on new thread)
* @warning Only call when not running!
*/
2014-10-26 02:56:13 -02:00
void run ( ) override ;
2014-03-31 22:26:50 -04:00
/**
2015-04-28 19:03:01 -04:00
* Steps the emulation thread by a single CPU instruction (if the CPU is not already running)
2014-03-31 22:26:50 -04:00
* @note This function is thread-safe
*/
2015-07-13 17:27:12 +02:00
void ExecStep ( ) {
exec_step = true ;
running_cv . notify_all ( ) ;
}
2014-03-31 22:26:50 -04:00
/**
2015-04-28 19:03:01 -04:00
* Sets whether the emulation thread is running or not
* @param running Boolean value, set the emulation thread to running if true
2014-03-31 22:26:50 -04:00
* @note This function is thread-safe
*/
2015-05-16 11:56:00 -06:00
void SetRunning ( bool running ) {
std : : unique_lock < std : : mutex > lock ( running_mutex ) ;
this - > running = running ;
lock . unlock ( ) ;
running_cv . notify_all ( ) ;
}
2014-03-31 22:26:50 -04:00
2014-04-03 21:24:07 -04:00
/**
2015-04-28 19:03:01 -04:00
* Check if the emulation thread is running or not
* @return True if the emulation thread is running, otherwise false
2015-04-16 23:31:14 -04:00
* @note This function is thread-safe
*/
2015-04-28 19:03:01 -04:00
bool IsRunning ( ) { return running ; }
2015-04-16 23:31:14 -04:00
/**
2015-04-30 19:46:50 -04:00
* Requests for the emulation thread to stop running
2015-04-16 23:31:14 -04:00
*/
2015-04-30 19:46:50 -04:00
void RequestStop ( ) {
2015-04-29 00:01:41 -04:00
stop_run = true ;
2015-05-16 11:56:00 -06:00
SetRunning ( false ) ;
2015-04-29 00:01:41 -04:00
} ;
2014-03-31 22:26:50 -04:00
private :
2015-04-28 19:03:01 -04:00
bool exec_step ;
bool running ;
2014-08-25 03:42:52 +10:00
std : : atomic < bool > stop_run ;
2015-05-16 11:56:00 -06:00
std : : mutex running_mutex ;
std : : condition_variable running_cv ;
2014-03-31 22:26:50 -04:00
GRenderWindow * render_window ;
signals :
/**
2015-01-07 12:14:23 +01:00
* Emitted when the CPU has halted execution
2014-10-12 18:14:57 +02:00
*
2014-03-31 22:26:50 -04:00
* @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
*/
2015-01-07 12:14:23 +01:00
void DebugModeEntered ( ) ;
2015-05-25 20:34:09 +02:00
2015-01-07 12:14:23 +01:00
/**
* Emitted right before the CPU continues execution
*
* @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
*/
void DebugModeLeft ( ) ;
2014-03-31 22:26:50 -04:00
} ;
class GRenderWindow : public QWidget , public EmuWindow
{
2014-08-25 00:47:00 +10:00
Q_OBJECT
2014-03-31 22:26:50 -04:00
public :
2015-04-29 00:01:41 -04:00
GRenderWindow ( QWidget * parent , EmuThread * emu_thread ) ;
2014-03-31 22:26:50 -04:00
// EmuWindow implementation
2014-10-26 02:56:13 -02:00
void SwapBuffers ( ) override ;
void MakeCurrent ( ) override ;
void DoneCurrent ( ) override ;
void PollEvents ( ) override ;
2014-03-31 22:26:50 -04:00
void BackupGeometry ( ) ;
void RestoreGeometry ( ) ;
void restoreGeometry ( const QByteArray & geometry ) ; // overridden
2014-10-12 18:14:57 +02:00
QByteArray saveGeometry ( ) ; // overridden
2014-03-31 22:26:50 -04:00
2015-09-10 23:42:45 +02:00
qreal windowPixelRatio ( ) ;
2015-09-05 12:29:44 +02:00
void closeEvent ( QCloseEvent * event ) override ;
2014-10-26 02:56:13 -02:00
void keyPressEvent ( QKeyEvent * event ) override ;
void keyReleaseEvent ( QKeyEvent * event ) override ;
2014-03-31 22:26:50 -04:00
2015-03-08 03:42:40 -04:00
void mousePressEvent ( QMouseEvent * event ) override ;
void mouseMoveEvent ( QMouseEvent * event ) override ;
void mouseReleaseEvent ( QMouseEvent * event ) override ;
2014-09-12 17:06:13 -07:00
void ReloadSetKeymaps ( ) override ;
2014-10-12 18:14:57 +02:00
void OnClientAreaResized ( unsigned width , unsigned height ) ;
2014-08-25 01:49:34 +10:00
public slots :
2014-10-12 18:14:57 +02:00
void moveContext ( ) ; // overridden
2014-08-25 00:47:00 +10:00
2015-04-30 19:46:50 -04:00
void OnEmulationStarting ( EmuThread * emu_thread ) ;
void OnEmulationStopping ( ) ;
2015-09-04 15:55:48 +02:00
void OnFramebufferSizeChanged ( ) ;
2015-04-29 00:01:41 -04:00
2015-09-05 12:29:44 +02:00
signals :
/// Emitted when the window is closed
void Closed ( ) ;
2014-03-31 22:26:50 -04:00
private :
2014-10-12 22:46:33 +02:00
void OnMinimalClientAreaChangeRequest ( const std : : pair < unsigned , unsigned > & minimal_size ) override ;
2015-08-26 22:04:12 +02:00
GGLWidgetInternal * child ;
2014-03-31 22:26:50 -04:00
QByteArray geometry ;
2014-09-08 21:46:02 -07:00
2014-09-12 17:06:13 -07:00
/// Device id of keyboard for use with KeyMap
2014-09-08 21:46:02 -07:00
int keyboard_id ;
2015-04-29 00:01:41 -04:00
EmuThread * emu_thread ;
2015-09-04 15:55:48 +02:00
protected :
void showEvent ( QShowEvent * event ) override ;
2014-03-31 22:26:50 -04:00
} ;