OSDN Git Service

bce27207ea568b055dcbe4537c83d2d51afda8c7
[csp-qt/common_source_project-fm7.git] / source / src / qt / gui / draw_thread.cpp
1 /*
2         Skelton for retropc emulator
3         Author : Takeda.Toshiya
4         Port to Qt : K.Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2006.08.18 -
6         License : GPLv2
7         History : 2015.11.10 Split from qt_main.cpp
8         [ win32 main ] -> [ Qt main ] -> [Drawing]
9 */
10
11 #include <Qt>
12 #include <QApplication>
13 #include <QImage>
14 #include <QGuiApplication>
15 #include <QSemaphore>
16 #include <QScreen>
17 #include <QWaitCondition>
18
19 #include <SDL.h>
20 #include "emu.h"
21 #include "osd.h"
22 #include "vm/vm.h"
23
24 #include "qt_main.h"
25 #include "csp_logger.h"
26 #include "mainwidget_base.h"
27 #include "draw_thread.h"
28 #include "gl2/qt_glutil_gl2_0.h"
29 #include "config.h"
30
31
32 DrawThreadClass::DrawThreadClass(OSD *o, CSP_Logger *logger,QObject *parent) : QThread(parent) {
33         MainWindow = (Ui_MainWindowBase *)parent;
34         glv = MainWindow->getGraphicsView();
35         p_osd = o;
36         csp_logger = logger;
37         using_flags = NULL;
38         if(p_osd != NULL) using_flags = p_osd->get_config_flags();
39         screen = QGuiApplication::primaryScreen();
40         
41         draw_screen_buffer = NULL;
42         
43         do_change_refresh_rate(screen->refreshRate());
44         connect(screen, SIGNAL(refreshRateChanged(qreal)), this, SLOT(do_change_refresh_rate(qreal)));
45         connect(this, SIGNAL(sig_update_screen(bitmap_t *)), glv, SLOT(update_screen(bitmap_t *)), Qt::QueuedConnection);
46         
47         connect(this, SIGNAL(sig_update_osd()), glv, SLOT(update_osd()), Qt::QueuedConnection);
48         connect(this, SIGNAL(sig_push_frames_to_avio(int, int, int)), glv->extfunc, SLOT(paintGL_OffScreen(int, int, int)));
49         //connect(this, SIGNAL(sig_call_draw_screen()), p_osd, SLOT(draw_screen()));
50         //connect(this, SIGNAL(sig_call_no_draw_screen()), p_osd, SLOT(no_draw_screen()));
51         use_separate_thread_draw = true;
52         if(using_flags->get_config_ptr() != NULL) {
53                 use_separate_thread_draw = using_flags->get_config_ptr()->use_separate_thread_draw;
54         }
55         rec_frame_width = 640;
56         rec_frame_height = 480;
57         rec_frame_count = -1;
58         emu_frame_rate = 1000.0 / 30.0;
59         wait_count = emu_frame_rate;
60         wait_refresh = emu_frame_rate;
61         bDrawReq = true;
62         renderSemaphore = new QSemaphore(0);
63 }
64
65 DrawThreadClass::~DrawThreadClass()
66 {
67         if(renderSemaphore != NULL) {
68                 while(renderSemaphore->available() <= 0) renderSemaphore->release(1);
69                 delete renderSemaphore;
70         }
71
72 }
73
74 void DrawThreadClass::SetEmu(EMU *p)
75 {
76         //p_emu = p;
77         p_osd = p->get_osd();
78 }
79
80 void DrawThreadClass::do_set_frames_per_second(double fps)
81 {
82         double _n = 1000.0 / (fps * 2.0);
83         emu_frame_rate = _n;
84         wait_count += (_n * 1.0);
85 }
86
87 void DrawThreadClass::doDrawMain(bool flag)
88 {
89         p_osd->do_decode_movie(1);
90         if(flag) {
91                 draw_frames = p_osd->draw_screen();
92         } else {
93                 draw_frames = p_osd->no_draw_screen();
94         }
95         emit sig_draw_frames(draw_frames);
96 }
97 void DrawThreadClass::doDraw(bool flag)
98 {
99         bRecentRenderStatus = flag;
100         if(!use_separate_thread_draw) {
101                 doDrawMain(flag);
102         } else {
103                 if(renderSemaphore != NULL) renderSemaphore->release(1);
104         }
105 }
106
107 void DrawThreadClass::doExit(void)
108 {
109         //csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL,
110         //                                        "DrawThread : Exit.");
111         bRunThread = false;
112         if(renderSemaphore != NULL) {
113                 while(renderSemaphore->available() <= 0) renderSemaphore->release(1);
114         }
115 }
116
117 void DrawThreadClass::do_draw_one_turn(bool _req_draw)
118 {
119         if((_req_draw) && (draw_screen_buffer != NULL)) {
120                 emit sig_update_screen(draw_screen_buffer);
121         } else {
122                 if(ncount == 0) emit sig_update_osd();
123         }
124         ncount++;
125         if(ncount >= 8) ncount = 0; 
126         if(rec_frame_count > 0) {
127                 emit sig_push_frames_to_avio(rec_frame_count,
128                                                                          rec_frame_width, rec_frame_height);
129                 rec_frame_count = -1;
130         }
131 }
132
133 void DrawThreadClass::doWork(const QString &param)
134 {
135         ncount = 0;
136         bRunThread = true;
137         double _rate = 1000.0 / 30.0;
138         bDrawReq = false;
139         if(renderSemaphore == NULL) goto __exit;
140         do {
141                 _rate = (wait_refresh < emu_frame_rate) ? emu_frame_rate : wait_refresh;
142                 if(_rate < 2.0) {
143                         wait_factor = 2.0;
144                 } else {
145                         wait_factor = (int)_rate - 1;
146                 }
147                 if(renderSemaphore->tryAcquire(1, wait_factor)) { // Success
148                         if(!bRunThread) break;
149                         volatile bool _b = bRecentRenderStatus;
150                         bRecentRenderStatus = false;
151                         doDrawMain(_b);
152                 }
153                 if(!bRunThread) break;
154                 volatile bool _d = bDrawReq;
155                 if(draw_screen_buffer == NULL) _d = false;
156                 if((_d) && (draw_screen_buffer != NULL)) bDrawReq = false;
157                 do_draw_one_turn(_d);
158         } while(bRunThread);
159 __exit:
160         csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL,
161                                                   "DrawThread : Exit.");
162         this->exit(0);
163 }
164
165 void DrawThreadClass::do_change_refresh_rate(qreal rate)
166 {
167         refresh_rate = rate;    
168         wait_refresh = 1000.0 / (refresh_rate * 2.0);
169         wait_count += (wait_refresh * 1.0);
170 }
171
172 void DrawThreadClass::do_update_screen(bitmap_t *p)
173 {
174         draw_screen_buffer = p;
175         bDrawReq = true;
176 }
177         
178 void DrawThreadClass::do_req_encueue_video(int count, int width, int height)
179 {
180         rec_frame_width = width;
181         rec_frame_height = height;
182         rec_frame_count = count;
183 }
184