OSDN Git Service

[Qt][DRAW_THREAD] New (more accurate) draw scheduler.
[csp-qt/common_source_project-fm7.git] / source / src / qt / gui / draw_thread.cpp
index 62e35fd..16ea756 100644 (file)
@@ -15,8 +15,8 @@
 #include <QSemaphore>
 #include <QScreen>
 #include <QWaitCondition>
+#include <QElapsedTimer>
 
-#include <SDL.h>
 #include "emu.h"
 #include "osd.h"
 #include "vm/vm.h"
@@ -37,20 +37,27 @@ DrawThreadClass::DrawThreadClass(OSD *o, CSP_Logger *logger,QObject *parent) : Q
        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;
@@ -59,6 +66,12 @@ DrawThreadClass::DrawThreadClass(OSD *o, CSP_Logger *logger,QObject *parent) : Q
        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()
@@ -67,6 +80,10 @@ DrawThreadClass::~DrawThreadClass()
                while(renderSemaphore->available() <= 0) renderSemaphore->release(1);
                delete renderSemaphore;
        }
+       if(textureMappingSemaphore != NULL) {
+               while(textureMappingSemaphore->available() <= 0) textureMappingSemaphore->release(1);
+               delete textureMappingSemaphore;
+       }
 
 }
 
@@ -83,14 +100,19 @@ void DrawThreadClass::do_set_frames_per_second(double fps)
        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)
@@ -116,7 +138,7 @@ void DrawThreadClass::doExit(void)
 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();
        }
@@ -127,6 +149,7 @@ void DrawThreadClass::do_draw_one_turn(bool _req_draw)
                                                                         rec_frame_width, rec_frame_height);
                rec_frame_count = -1;
        }
+       mapped_drawn = false;
 }
 
 void DrawThreadClass::doWork(const QString &param)
@@ -135,25 +158,39 @@ void DrawThreadClass::doWork(const QString &param)
        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,
@@ -168,10 +205,11 @@ void DrawThreadClass::do_change_refresh_rate(qreal rate)
        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)
@@ -180,4 +218,43 @@ 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);
+               }
+       }
+}