#include <QSemaphore>
#include <QScreen>
#include <QWaitCondition>
+#include <QElapsedTimer>
-#include <SDL.h>
#include "emu.h"
#include "osd.h"
#include "vm/vm.h"
using_flags = NULL;
if(p_osd != NULL) using_flags = p_osd->get_config_flags();
screen = QGuiApplication::primaryScreen();
-
+
+ is_shared_glcontext = false;
+ glContext = NULL;
draw_screen_buffer = NULL;
-
+ if(p_osd != NULL) {
+ p_osd->set_glview(glv);
+ //printf("OSD/Context sharing succeeded.ADDR=%08x GLES=%s\n", glContext, (glContext->isOpenGLES()) ? "YES" : "NO");
+ }
do_change_refresh_rate(screen->refreshRate());
connect(screen, SIGNAL(refreshRateChanged(qreal)), this, SLOT(do_change_refresh_rate(qreal)));
- connect(this, SIGNAL(sig_update_screen(bitmap_t *)), glv, SLOT(update_screen(bitmap_t *)), Qt::QueuedConnection);
+ connect(this, SIGNAL(sig_update_screen(void *, bool)), glv, SLOT(update_screen(void *, bool)), Qt::QueuedConnection);
connect(this, SIGNAL(sig_update_osd()), glv, SLOT(update_osd()), Qt::QueuedConnection);
connect(this, SIGNAL(sig_push_frames_to_avio(int, int, int)), glv->extfunc, SLOT(paintGL_OffScreen(int, int, int)));
+
//connect(this, SIGNAL(sig_call_draw_screen()), p_osd, SLOT(draw_screen()));
//connect(this, SIGNAL(sig_call_no_draw_screen()), p_osd, SLOT(no_draw_screen()));
- use_separate_thread_draw = false;
- if(using_flags != NULL) use_separate_thread_draw = using_flags->get_config_ptr()->use_separate_thread_draw;
-
+ use_separate_thread_draw = true;
+ if(using_flags->get_config_ptr() != NULL) {
+ use_separate_thread_draw = using_flags->get_config_ptr()->use_separate_thread_draw;
+ }
rec_frame_width = 640;
rec_frame_height = 480;
rec_frame_count = -1;
wait_refresh = emu_frame_rate;
bDrawReq = true;
renderSemaphore = new QSemaphore(0);
+ textureMappingSemaphore = new QSemaphore(0);
+ mapping_status = false;
+ mapping_pointer = NULL;
+ mapping_width = 0;
+ mapping_height = 0;
+ mapped_drawn = false;
}
DrawThreadClass::~DrawThreadClass()
while(renderSemaphore->available() <= 0) renderSemaphore->release(1);
delete renderSemaphore;
}
+ if(textureMappingSemaphore != NULL) {
+ while(textureMappingSemaphore->available() <= 0) textureMappingSemaphore->release(1);
+ delete textureMappingSemaphore;
+ }
}
wait_count += (_n * 1.0);
}
+// Note: Mapping vram from draw_thread does'nt work well.
+// This feature might be disable. 20180728 K.Ohta.
void DrawThreadClass::doDrawMain(bool flag)
{
+ //req_map_screen_texture();
p_osd->do_decode_movie(1);
if(flag) {
draw_frames = p_osd->draw_screen();
} else {
draw_frames = p_osd->no_draw_screen();
}
+ //req_unmap_screen_texture();
+
emit sig_draw_frames(draw_frames);
}
void DrawThreadClass::doDraw(bool flag)
void DrawThreadClass::do_draw_one_turn(bool _req_draw)
{
if((_req_draw) && (draw_screen_buffer != NULL)) {
- emit sig_update_screen(draw_screen_buffer);
+ emit sig_update_screen((void *)draw_screen_buffer, mapped_drawn);
} else {
if(ncount == 0) emit sig_update_osd();
}
rec_frame_width, rec_frame_height);
rec_frame_count = -1;
}
+ mapped_drawn = false;
}
void DrawThreadClass::doWork(const QString ¶m)
bRunThread = true;
double _rate = 1000.0 / 30.0;
bDrawReq = false;
- if(renderSemaphore == NULL) goto __exit;
+ QElapsedTimer tick_timer;
+ tick_timer.start();
+ quint64 elapsed = (quint64)_rate;
+ double drate;
+ if(renderSemaphore == NULL) {
+ QSemaphore *s = new QSemaphore(0);
+ if(s == NULL) goto __exit;
+ renderSemaphore = s;
+ }
+
do {
- _rate = (wait_refresh < emu_frame_rate) ? emu_frame_rate : wait_refresh;
- if(_rate < 2.0) {
- wait_factor = 2.0;
+ //_rate = (wait_refresh < emu_frame_rate) ? emu_frame_rate : wait_refresh;
+ _rate = 1.0e3 / p_osd->vm_frame_rate(); // FPS to msec
+ drate = (double)elapsed / 1.0e6; // nsec to msec
+ if(_rate >= drate) {
+ wait_factor = (int)nearbyint(_rate - drate) + 3;
} else {
- wait_factor = (int)_rate - 1;
+ wait_factor = 3;
}
+ //printf("RATE:%f ELAPSED: %f WAIT_FACTOR:%d\n", _rate, drate, wait_factor);
if(renderSemaphore->tryAcquire(1, wait_factor)) { // Success
- if(!bRunThread) break;
+ if(!bRunThread) goto __exit;
volatile bool _b = bRecentRenderStatus;
bRecentRenderStatus = false;
doDrawMain(_b);
}
- if(!bRunThread) break;
+ if(!bRunThread) goto __exit;
volatile bool _d = bDrawReq;
if(draw_screen_buffer == NULL) _d = false;
if((_d) && (draw_screen_buffer != NULL)) bDrawReq = false;
do_draw_one_turn(_d);
+ elapsed = tick_timer.nsecsElapsed();
+ tick_timer.start();
} while(bRunThread);
__exit:
csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GENERAL,
wait_count += (wait_refresh * 1.0);
}
-void DrawThreadClass::do_update_screen(bitmap_t *p)
+void DrawThreadClass::do_update_screen(void *p, bool is_mapped)
{
- draw_screen_buffer = p;
+ draw_screen_buffer = (bitmap_t*)p;
bDrawReq = true;
+ mapped_drawn = is_mapped;
}
void DrawThreadClass::do_req_encueue_video(int count, int width, int height)
rec_frame_height = height;
rec_frame_count = count;
}
+// Note: Mapping vram from draw_thread does'nt work well.
+// This feature might be disable. 20180728 K.Ohta.
+void DrawThreadClass::req_map_screen_texture()
+{
+ mapping_status = false;
+ mapping_pointer = NULL;
+ mapping_width = 0;
+ mapping_height = 0;
+ if(glv->is_ready_to_map_vram_texture()) {
+ textureMappingSemaphore->acquire();
+ //mapping_pointer = (scrntype_t *)(glv->do_map_vram_texture(&mapping_width, &mapping_height));
+ //if(mapping_pointer == NULL) {
+ // mapping_status = false;
+ // mapping_pointer = NULL;
+ // mapping_width = 0;
+ // mapping_height = 0;
+ //} else {
+ // mapping_status = true;
+ //}
+ //p_osd->do_set_screen_map_texture_address(mapping_pointer, mapping_width, mapping_height);
+ }
+}
+
+void DrawThreadClass::req_unmap_screen_texture()
+{
+ if(mapping_status) {
+ if(glv->is_ready_to_map_vram_texture()) {
+ emit sig_unmap_texture();
+ textureMappingSemaphore->acquire();
+
+ //glv->do_unmap_vram_texture();
+ //mapping_status = false;
+ //mapping_pointer = NULL;
+ //mapping_width = 0;
+ //mapping_height = 0;
+ //p_osd->do_set_screen_map_texture_address(mapping_pointer, mapping_width, mapping_height);
+ }
+ }
+}