2 Skelton for retropc emulator
3 Author : Takeda.Toshiya
4 Port to Qt : K.Ohta <whatisthis.sowhat _at_ gmail.com>
7 History : 2015.11.10 Split from qt_main.cpp
8 [ win32 main ] -> [ Qt main ] -> [Drawing]
12 #include <QApplication>
14 #include <QGuiApplication>
17 #include <QWaitCondition>
18 #include <QElapsedTimer>
25 #include "csp_logger.h"
26 #include "mainwidget_base.h"
27 #include "draw_thread.h"
28 #include "gl2/qt_glutil_gl2_0.h"
32 DrawThreadClass::DrawThreadClass(OSD *o, CSP_Logger *logger,QObject *parent) : QThread(parent) {
33 MainWindow = (Ui_MainWindowBase *)parent;
34 glv = MainWindow->getGraphicsView();
38 if(p_osd != NULL) using_flags = p_osd->get_config_flags();
39 screen = QGuiApplication::primaryScreen();
41 is_shared_glcontext = false;
43 draw_screen_buffer = NULL;
45 p_osd->set_glview(glv);
46 //printf("OSD/Context sharing succeeded.ADDR=%08x GLES=%s\n", glContext, (glContext->isOpenGLES()) ? "YES" : "NO");
48 do_change_refresh_rate(screen->refreshRate());
49 connect(screen, SIGNAL(refreshRateChanged(qreal)), this, SLOT(do_change_refresh_rate(qreal)));
50 connect(this, SIGNAL(sig_update_screen(void *, bool)), glv, SLOT(update_screen(void *, bool)), Qt::QueuedConnection);
52 connect(this, SIGNAL(sig_update_osd()), glv, SLOT(update_osd()), Qt::QueuedConnection);
53 connect(this, SIGNAL(sig_push_frames_to_avio(int, int, int)), glv->extfunc, SLOT(paintGL_OffScreen(int, int, int)));
55 //connect(this, SIGNAL(sig_call_draw_screen()), p_osd, SLOT(draw_screen()));
56 //connect(this, SIGNAL(sig_call_no_draw_screen()), p_osd, SLOT(no_draw_screen()));
57 use_separate_thread_draw = true;
58 if(using_flags->get_config_ptr() != NULL) {
59 use_separate_thread_draw = using_flags->get_config_ptr()->use_separate_thread_draw;
61 rec_frame_width = 640;
62 rec_frame_height = 480;
64 emu_frame_rate = 1000.0 / 30.0;
65 wait_count = emu_frame_rate;
66 wait_refresh = emu_frame_rate;
68 renderSemaphore = new QSemaphore(0);
69 textureMappingSemaphore = new QSemaphore(0);
70 mapping_status = false;
71 mapping_pointer = NULL;
77 DrawThreadClass::~DrawThreadClass()
79 if(renderSemaphore != NULL) {
80 while(renderSemaphore->available() <= 0) renderSemaphore->release(1);
81 delete renderSemaphore;
83 if(textureMappingSemaphore != NULL) {
84 while(textureMappingSemaphore->available() <= 0) textureMappingSemaphore->release(1);
85 delete textureMappingSemaphore;
90 void DrawThreadClass::SetEmu(EMU *p)
96 void DrawThreadClass::do_set_frames_per_second(double fps)
98 double _n = 1000.0 / (fps * 2.0);
100 wait_count += (_n * 1.0);
103 // Note: Mapping vram from draw_thread does'nt work well.
104 // This feature might be disable. 20180728 K.Ohta.
105 void DrawThreadClass::doDrawMain(bool flag)
107 //req_map_screen_texture();
108 p_osd->do_decode_movie(1);
110 draw_frames = p_osd->draw_screen();
112 draw_frames = p_osd->no_draw_screen();
114 //req_unmap_screen_texture();
116 emit sig_draw_frames(draw_frames);
118 void DrawThreadClass::doDraw(bool flag)
120 bRecentRenderStatus = flag;
121 if(!use_separate_thread_draw) {
124 if(renderSemaphore != NULL) renderSemaphore->release(1);
128 void DrawThreadClass::doExit(void)
130 //csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL,
131 // "DrawThread : Exit.");
133 if(renderSemaphore != NULL) {
134 while(renderSemaphore->available() <= 0) renderSemaphore->release(1);
138 void DrawThreadClass::do_draw_one_turn(bool _req_draw)
140 if((_req_draw) && (draw_screen_buffer != NULL)) {
141 emit sig_update_screen((void *)draw_screen_buffer, mapped_drawn);
143 if(ncount == 0) emit sig_update_osd();
146 if(ncount >= 8) ncount = 0;
147 if(rec_frame_count > 0) {
148 emit sig_push_frames_to_avio(rec_frame_count,
149 rec_frame_width, rec_frame_height);
150 rec_frame_count = -1;
152 mapped_drawn = false;
155 void DrawThreadClass::doWork(const QString ¶m)
159 double _rate = 1000.0 / 30.0;
161 QElapsedTimer tick_timer;
163 quint64 elapsed = (quint64)_rate;
165 if(renderSemaphore == NULL) {
166 QSemaphore *s = new QSemaphore(0);
167 if(s == NULL) goto __exit;
172 //_rate = (wait_refresh < emu_frame_rate) ? emu_frame_rate : wait_refresh;
173 _rate = 1.0e3 / p_osd->vm_frame_rate(); // FPS to msec
174 drate = (double)elapsed / 1.0e6; // nsec to msec
176 wait_factor = (int)nearbyint(_rate - drate) + 3;
180 //printf("RATE:%f ELAPSED: %f WAIT_FACTOR:%d\n", _rate, drate, wait_factor);
181 if(renderSemaphore->tryAcquire(1, wait_factor)) { // Success
182 if(!bRunThread) goto __exit;
183 volatile bool _b = bRecentRenderStatus;
184 bRecentRenderStatus = false;
187 if(!bRunThread) goto __exit;
188 volatile bool _d = bDrawReq;
189 if(draw_screen_buffer == NULL) _d = false;
190 if((_d) && (draw_screen_buffer != NULL)) bDrawReq = false;
191 do_draw_one_turn(_d);
192 elapsed = tick_timer.nsecsElapsed();
196 csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL,
197 "DrawThread : Exit.");
201 void DrawThreadClass::do_change_refresh_rate(qreal rate)
204 wait_refresh = 1000.0 / (refresh_rate * 2.0);
205 wait_count += (wait_refresh * 1.0);
208 void DrawThreadClass::do_update_screen(void *p, bool is_mapped)
210 draw_screen_buffer = (bitmap_t*)p;
212 mapped_drawn = is_mapped;
215 void DrawThreadClass::do_req_encueue_video(int count, int width, int height)
217 rec_frame_width = width;
218 rec_frame_height = height;
219 rec_frame_count = count;
221 // Note: Mapping vram from draw_thread does'nt work well.
222 // This feature might be disable. 20180728 K.Ohta.
223 void DrawThreadClass::req_map_screen_texture()
225 mapping_status = false;
226 mapping_pointer = NULL;
229 if(glv->is_ready_to_map_vram_texture()) {
230 textureMappingSemaphore->acquire();
231 //mapping_pointer = (scrntype_t *)(glv->do_map_vram_texture(&mapping_width, &mapping_height));
232 //if(mapping_pointer == NULL) {
233 // mapping_status = false;
234 // mapping_pointer = NULL;
235 // mapping_width = 0;
236 // mapping_height = 0;
238 // mapping_status = true;
240 //p_osd->do_set_screen_map_texture_address(mapping_pointer, mapping_width, mapping_height);
244 void DrawThreadClass::req_unmap_screen_texture()
247 if(glv->is_ready_to_map_vram_texture()) {
248 emit sig_unmap_texture();
249 textureMappingSemaphore->acquire();
251 //glv->do_unmap_vram_texture();
252 //mapping_status = false;
253 //mapping_pointer = NULL;
255 //mapping_height = 0;
256 //p_osd->do_set_screen_map_texture_address(mapping_pointer, mapping_width, mapping_height);