From 46b531b0a03ccb325cd9254f684e8d9f8221b256 Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Fri, 31 Jan 2020 13:33:44 +0200 Subject: [PATCH 1/6] GUI: Remove redundant ClosedNoResume state --- libswirl/gui/gui.cpp | 10 +++++----- libswirl/gui/gui_partials.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libswirl/gui/gui.cpp b/libswirl/gui/gui.cpp index 147170834b..9f24e29fc4 100644 --- a/libswirl/gui/gui.cpp +++ b/libswirl/gui/gui.cpp @@ -51,6 +51,7 @@ #include "hw/maple/maple_if.h" #include "libswirl.h" +#include "gui/gui_renderer.h" bool game_started; @@ -363,14 +364,13 @@ struct ReicastUI_impl : GUI { if (!game_file.empty()) { if (gui_start_game(game_file)) - gui_state = ClosedNoResume; + gui_state = Closed; } else gui_render_content(); } break; case Closed: - case ClosedNoResume: break; case Onboarding: gui_render_onboarding(); @@ -384,7 +384,7 @@ struct ReicastUI_impl : GUI { break; } - if (gui_state == ClosedNoResume) + if (gui_state == Closed) gui_state = Closed; } @@ -924,7 +924,7 @@ struct ReicastUI_impl : GUI { { cfgSetVirtual("config", "image", ""); if (gui_start_game("")) - gui_state = ClosedNoResume; + gui_state = Closed; } ImGui::PopID(); #endif @@ -939,7 +939,7 @@ struct ReicastUI_impl : GUI { if (ImGui::Selectable(game.name.c_str())) { if (gui_start_game(game.path)) - gui_state = ClosedNoResume; + gui_state = Closed; } ImGui::PopID(); } diff --git a/libswirl/gui/gui_partials.h b/libswirl/gui/gui_partials.h index 8be8491a4f..b25dbb2dde 100644 --- a/libswirl/gui/gui_partials.h +++ b/libswirl/gui/gui_partials.h @@ -43,6 +43,6 @@ extern f32 mo_wheel_delta; extern int screen_dpi; -typedef enum { Welcome, Closed, Commands, Settings, ClosedNoResume, Main, Onboarding, VJoyEdit, VJoyEditCommands } GuiState; +typedef enum { Welcome, Closed, Commands, Settings, Main, Onboarding, VJoyEdit, VJoyEditCommands } GuiState; extern GuiState gui_state; void ImGui_Impl_NewFrame(); From 998ddc3d283efbd8c6c05059d5eafefdeab13d47 Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Fri, 31 Jan 2020 13:36:08 +0200 Subject: [PATCH 2/6] GUI/REND: Move Vjoy OSD to gui_renderer.cpp, abstract away from rend_if --- libswirl/gui/gui_renderer.cpp | 366 +++++++++++++++++++++++++++++++- libswirl/gui/gui_renderer.h | 2 + libswirl/hw/pvr/Renderer_if.cpp | 8 +- libswirl/hw/pvr/Renderer_if.h | 6 +- libswirl/rend/gl4/gl4rend.cpp | 11 - libswirl/rend/gles/gles.h | 11 +- libswirl/rend/gles/glesrend.cpp | 311 --------------------------- libswirl/rend/norend/norend.cpp | 2 - 8 files changed, 369 insertions(+), 348 deletions(-) diff --git a/libswirl/gui/gui_renderer.cpp b/libswirl/gui/gui_renderer.cpp index d59434712a..3b8a3268db 100644 --- a/libswirl/gui/gui_renderer.cpp +++ b/libswirl/gui/gui_renderer.cpp @@ -5,6 +5,8 @@ #include "gui_renderer.h" #include "oslib/oslib.h" +#include "input/gamepad.h" +#include "gui/gui_partials.h" std::unique_ptr g_GUIRenderer; @@ -86,6 +88,331 @@ static void findGLVersion() } } + +//TODO: FIXME HAVING THESE HERE IS A BIT OF A HACK +// THIS FILE IS SUPPOSED TO BE MOSTLY PORTABLE + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// OSD + + +const char* OSD_VertexShader = + "\ +%s \n\ +#define TARGET_GL %s \n\ + \n\ +#define GLES2 0 \n\ +#define GLES3 1 \n\ +#define GL2 2 \n\ +#define GL3 3 \n\ + \n\ +#if TARGET_GL == GL2 \n\ +#define highp \n\ +#define lowp \n\ +#define mediump \n\ +#endif \n\ +#if TARGET_GL == GLES2 || TARGET_GL == GL2 \n\ +#define in attribute \n\ +#define out varying \n\ +#endif \n\ + \n\ +uniform highp vec4 scale; \n\ + \n\ +in highp vec4 in_pos; \n\ +in lowp vec4 in_base; \n\ +in mediump vec2 in_uv; \n\ + \n\ +out lowp vec4 vtx_base; \n\ +out mediump vec2 vtx_uv; \n\ + \n\ +void main() \n\ +{ \n\ + vtx_base = in_base; \n\ + vtx_uv = in_uv; \n\ + highp vec4 vpos = in_pos; \n\ + \n\ + vpos.w = 1.0; \n\ + vpos.z = vpos.w; \n\ + vpos.xy = vpos.xy * scale.xy - scale.zw; \n\ + gl_Position = vpos; \n\ +}"; + +const char* OSD_Shader = + "\ +%s \n\ +#define TARGET_GL %s \n\ + \n\ +#define GLES2 0 \n\ +#define GLES3 1 \n\ +#define GL2 2 \n\ +#define GL3 3 \n\ + \n\ +#if TARGET_GL == GL2 \n\ +#define highp \n\ +#define lowp \n\ +#define mediump \n\ +#endif \n\ +#if TARGET_GL != GLES2 && TARGET_GL != GL2 \n\ +out highp vec4 FragColor; \n\ +#define gl_FragColor FragColor \n\ +#else \n\ +#define in varying \n\ +#define texture texture2D \n\ +#endif \n\ + \n\ +in lowp vec4 vtx_base; \n\ +in mediump vec2 vtx_uv; \n\ +/* Vertex input*/ \n\ +uniform sampler2D tex; \n\ +void main() \n\ +{ \n\ + mediump vec2 uv=vtx_uv; \n\ + uv.y=1.0-uv.y; \n\ + gl_FragColor = vtx_base*texture(tex,uv.st); \n\ +}"; + + +extern u16 kcode[4]; +extern u8 rt[4],lt[4]; + +#if defined(_ANDROID) +extern float vjoy_pos[14][8]; +#else + +float vjoy_pos[14][8]= +{ + {24+0,24+64,64,64}, //LEFT + {24+64,24+0,64,64}, //UP + {24+128,24+64,64,64}, //RIGHT + {24+64,24+128,64,64}, //DOWN + + {440+0,280+64,64,64}, //X + {440+64,280+0,64,64}, //Y + {440+128,280+64,64,64}, //B + {440+64,280+128,64,64}, //A + + {320-32,360+32,64,64}, //Start + + {440,200,90,64}, //RT + {542,200,90,64}, //LT + + {-24,128+224,128,128}, //ANALOG_RING + {96,320,64,64}, //ANALOG_POINT + {1} +}; +#endif // !_ANDROID + +struct +{ + GLuint program; + GLuint scaleLocation; + GLuint tex; + GLuint vao; + GLuint geom; +} gl_osd; + + +void gl_load_osd_resources() +{ + char vshader[8192]; + char fshader[8192]; + + sprintf(vshader, OSD_VertexShader, gl.glsl_version_header, gl.gl_version); + sprintf(fshader, OSD_Shader, gl.glsl_version_header, gl.gl_version); + + gl_osd.program = gl_CompileAndLink(vshader, fshader); + gl_osd.scaleLocation = glGetUniformLocation(gl_osd.program, "scale"); + glUniform1i(glGetUniformLocation(gl_osd.program, "tex"), 0); //bind osd texture to slot 0 + +#ifdef _ANDROID + int w, h; + if (gl_osd.tex == 0) + gl_osd.tex = loadPNG(get_readonly_data_path(DATA_PATH "buttons.png"), w, h); +#endif +} + +void gl_free_osd_resources() +{ + if (gl_osd.program != 0) { + glcache.DeleteProgram(gl_osd.program); + gl_osd.program = 0; + } + + if (gl_osd.tex != 0) { + glcache.DeleteTextures(1, &gl_osd.tex); + gl_osd.tex = 0; + } +} + + +static vector osd_vertices; + +static const float vjoy_sz[2][14] = { + { 64,64,64,64, 64,64,64,64, 64, 90,90, 128, 64 }, + { 64,64,64,64, 64,64,64,64, 64, 64,64, 128, 64 }, +}; + +void HideOSD() +{ + vjoy_pos[13][0] = 0; + vjoy_pos[13][1] = 0; + vjoy_pos[13][2] = 0; + vjoy_pos[13][3] = 0; +} + +static void DrawButton(float* xy, u32 state) +{ + Vertex vtx; + + vtx.z = 1; + + vtx.col[0]=vtx.col[1]=vtx.col[2]=(0x7F-0x40*state/255)*vjoy_pos[13][0]; + + vtx.col[3]=0xA0*vjoy_pos[13][4]; + + vjoy_pos[13][4]+=(vjoy_pos[13][0]-vjoy_pos[13][4])/2; + + + + vtx.x = xy[0]; vtx.y = xy[1]; + vtx.u=xy[4]; vtx.v=xy[5]; + osd_vertices.push_back(vtx); + + vtx.x = xy[0] + xy[2]; vtx.y = xy[1]; + vtx.u=xy[6]; vtx.v=xy[5]; + osd_vertices.push_back(vtx); + + vtx.x = xy[0]; vtx.y = xy[1] + xy[3]; + vtx.u=xy[4]; vtx.v=xy[7]; + osd_vertices.push_back(vtx); + + vtx.x = xy[0] + xy[2]; vtx.y = xy[1] + xy[3]; + vtx.u=xy[6]; vtx.v=xy[7]; + osd_vertices.push_back(vtx); +} + +static void DrawButton2(float* xy, bool state) { DrawButton(xy,state?0:255); } + +static void osd_gen_vertices() +{ + osd_vertices.clear(); + DrawButton2(vjoy_pos[0],kcode[0] & DC_DPAD_LEFT); + DrawButton2(vjoy_pos[1],kcode[0] & DC_DPAD_UP); + DrawButton2(vjoy_pos[2],kcode[0] & DC_DPAD_RIGHT); + DrawButton2(vjoy_pos[3],kcode[0] & DC_DPAD_DOWN); + + DrawButton2(vjoy_pos[4],kcode[0] & DC_BTN_X); + DrawButton2(vjoy_pos[5],kcode[0] & DC_BTN_Y); + DrawButton2(vjoy_pos[6],kcode[0] & DC_BTN_B); + DrawButton2(vjoy_pos[7],kcode[0] & DC_BTN_A); + + DrawButton2(vjoy_pos[8],kcode[0] & DC_BTN_START); + + DrawButton(vjoy_pos[9],lt[0]); + + DrawButton(vjoy_pos[10],rt[0]); + + DrawButton2(vjoy_pos[11],1); + DrawButton2(vjoy_pos[12],0); +} + +#define OSD_TEX_W 512 +#define OSD_TEX_H 256 + +void OSD_DRAW(bool clear_screen) +{ +#ifdef _ANDROID + if (gl_osd.tex == 0) + gl_load_osd_resources(); + if (gl_osd.tex != 0) + { + osd_gen_vertices(); + + float u=0; + float v=0; + + for (int i=0;i<13;i++) + { + //umin,vmin,umax,vmax + vjoy_pos[i][4]=(u+1)/OSD_TEX_W; + vjoy_pos[i][5]=(v+1)/OSD_TEX_H; + + vjoy_pos[i][6]=((u+vjoy_sz[0][i]-1))/OSD_TEX_W; + vjoy_pos[i][7]=((v+vjoy_sz[1][i]-1))/OSD_TEX_H; + + u+=vjoy_sz[0][i]; + if (u>=OSD_TEX_W) + { + u-=OSD_TEX_W; + v+=vjoy_sz[1][i]; + } + //v+=vjoy_pos[i][3]; + } + + verify(glIsProgram(gl_osd.program)); + glcache.UseProgram(gl_osd.program); + + float scale_h = screen_height / 480.f; + float offs_x = (screen_width - scale_h * 640.f) / 2.f; + float scale[4]; + scale[0] = 2.f / (screen_width / scale_h); + scale[1]= -2.f / 480.f; + scale[2]= 1.f - 2.f * offs_x / screen_width; + scale[3]= -1.f; + glUniform4fv(gl_osd.scaleLocation, 1, scale); + + glActiveTexture(GL_TEXTURE0); + glcache.BindTexture(GL_TEXTURE_2D, gl_osd.tex); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glBufferData(GL_ARRAY_BUFFER, osd_vertices.size() * sizeof(Vertex), &osd_vertices[0], GL_STREAM_DRAW); glCheck(); + + glcache.Enable(GL_BLEND); + glcache.Disable(GL_DEPTH_TEST); + glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glcache.DepthMask(false); + glcache.DepthFunc(GL_ALWAYS); + + glcache.Disable(GL_CULL_FACE); + glcache.Disable(GL_SCISSOR_TEST); + glViewport(0, 0, screen_width, screen_height); + + if (clear_screen) + { + glcache.ClearColor(0.7f, 0.7f, 0.7f, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + } + int dfa = osd_vertices.size() / 4; + + for (int i = 0; i < dfa; i++) + glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4); + } +#endif + //g_GUI->RenderOSD(); +} + +void DrawOSD(bool clear_screen) +{ + + if (gl.gl_major >= 3) + glBindVertexArray(gl_osd.vao); + + glBindBuffer(GL_ARRAY_BUFFER, gl_osd.geom); glCheck(); + glEnableVertexAttribArray(VERTEX_POS_ARRAY); + glVertexAttribPointer(VERTEX_POS_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex,x)); + + glEnableVertexAttribArray(VERTEX_COL_BASE_ARRAY); + glVertexAttribPointer(VERTEX_COL_BASE_ARRAY, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex,col)); + + glEnableVertexAttribArray(VERTEX_UV_ARRAY); + glVertexAttribPointer(VERTEX_UV_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex,u)); + + OSD_DRAW(clear_screen); +} +// GUIRenderer + struct GUIRenderer_impl : GUIRenderer { std::atomic keepRunning; std::atomic frameDone; @@ -125,13 +452,15 @@ struct GUIRenderer_impl : GUIRenderer { if (cb) { if (cb()) { + DrawOSD(false); + g_GUI->RenderOSD(); if (!os_gl_swap()) // must re-create context { rv = false; } } } - else if (g_GUI->IsOpen() || g_GUI->IsVJoyEdit()) + else if (g_GUI->IsOpen()) { g_GUI->RenderUI(); @@ -140,6 +469,15 @@ struct GUIRenderer_impl : GUIRenderer { rv = false; } } + else if (g_GUI->IsVJoyEdit()) + { + DrawOSD(true); + + if (!os_gl_swap()) // must re-create context + { + rv = false; + } + } return rv; } @@ -153,7 +491,27 @@ struct GUIRenderer_impl : GUIRenderer { } } } - + + void CreateOSDResources() + { + glGenVertexArrays(1, &gl_osd.vao); + + //create vbos + glGenBuffers(1, &gl_osd.geom); + + gl_load_osd_resources(); + } + + void DestroyOSDResources() + { + gl_free_osd_resources(); + glDeleteBuffers(1, &gl_osd.geom); + gl_osd.geom = 0; + + glDeleteVertexArrays(1, &gl_osd.vao); + gl_osd.vao = 0; + } + bool CreateContext() { printf("CreateContext\n"); if (!os_gl_init((void*)libPvr_GetRenderTarget(), @@ -167,7 +525,8 @@ struct GUIRenderer_impl : GUIRenderer { ImGui_ImplOpenGL3_Init(); - // rend_init_renderer(); // is lazy init on callback/rend_frame + CreateOSDResources(); + //rend_init_renderer(sh4_cpu->vram.data); // is lazy init in rend_frame, sh4_cpu might not be known at this point printf("CreateContext Done\n"); return true; } @@ -175,6 +534,7 @@ struct GUIRenderer_impl : GUIRenderer { void DestroyContext() { printf("DestroyContext\n"); rend_term_renderer(); // also cleans texcache + DestroyOSDResources(); ImGui_ImplOpenGL3_Shutdown(); os_gl_term(); printf("DestroyContext Done\n"); diff --git a/libswirl/gui/gui_renderer.h b/libswirl/gui/gui_renderer.h index 127ec60dd4..576a8d4b0e 100644 --- a/libswirl/gui/gui_renderer.h +++ b/libswirl/gui/gui_renderer.h @@ -4,6 +4,8 @@ #include "gui.h" +void HideOSD(); + struct GUIRenderer { virtual void Start() = 0; // only sets the flag diff --git a/libswirl/hw/pvr/Renderer_if.cpp b/libswirl/hw/pvr/Renderer_if.cpp index b71fc67307..2e602ed465 100644 --- a/libswirl/hw/pvr/Renderer_if.cpp +++ b/libswirl/hw/pvr/Renderer_if.cpp @@ -177,7 +177,7 @@ void rend_term_renderer() fallback_renderer.reset(); } -static bool rend_frame(u8* vram, TA_context* ctx, bool draw_osd) { +static bool rend_frame(u8* vram, TA_context* ctx) { #if FIXME if (dump_frame_switch) { char name[32]; @@ -207,9 +207,6 @@ static bool rend_frame(u8* vram, TA_context* ctx, bool draw_osd) { bool do_swp = proc && renderer->RenderPVR(); - if (do_swp && draw_osd) - renderer->DrawOSD(false); - return do_swp; } @@ -417,7 +414,7 @@ void rend_start_render(u8* vram) verify(_pvrrc == ctx); - bool do_swp = rend_frame(vram, _pvrrc, true); + bool do_swp = rend_frame(vram, _pvrrc); if (_pvrrc->rend.isRTT) { pend_rend = false; @@ -460,7 +457,6 @@ void rend_end_render() } } - void rend_vblank() { if (!render_called && fb_dirty && FB_R_CTRL.fb_enable) diff --git a/libswirl/hw/pvr/Renderer_if.h b/libswirl/hw/pvr/Renderer_if.h index 223f343715..d1f15feb06 100644 --- a/libswirl/hw/pvr/Renderer_if.h +++ b/libswirl/hw/pvr/Renderer_if.h @@ -47,8 +47,6 @@ struct Renderer virtual void Present()=0; - virtual void DrawOSD(bool clear_screen) { } - virtual u32 GetTexture(TSP tsp, TCW tcw) { return 0; } virtual ~Renderer() { } @@ -58,6 +56,4 @@ extern bool renderer_enabled; // Signals the renderer thread to exit extern bool renderer_changed; // Signals the renderer thread to switch renderer extern bool RegisterRendererBackend(const rendererbackend_t& backend); -vector rend_get_backends(); - -void* rend_thread(void* p); \ No newline at end of file +vector rend_get_backends(); \ No newline at end of file diff --git a/libswirl/rend/gl4/gl4rend.cpp b/libswirl/rend/gl4/gl4rend.cpp index e66f610316..0e70424dac 100644 --- a/libswirl/rend/gl4/gl4rend.cpp +++ b/libswirl/rend/gl4/gl4rend.cpp @@ -538,8 +538,6 @@ static bool gl4_create_resources() create_modvol_shader(); - gl_load_osd_resources(); - // Create the buffer for Translucent poly params glGenBuffers(1, &gl4.vbo.tr_poly_params); // Bind it @@ -1040,7 +1038,6 @@ struct gl4rend : Renderer CollectCleanup(); - gl_free_osd_resources(); free_output_framebuffer(); gl41_term(); } @@ -1052,14 +1049,6 @@ struct gl4rend : Renderer void Present() { os_gl_swap(); } - void DrawOSD(bool clear_screen) - { - glBindVertexArray(gl4.vbo.main_vao); - glBindBuffer(GL_ARRAY_BUFFER, gl4.vbo.geometry); glCheck(); - - OSD_DRAW(clear_screen); - } - virtual u32 GetTexture(TSP tsp, TCW tcw) { return gl_GetTexture(vram, tsp, tcw); } diff --git a/libswirl/rend/gles/gles.h b/libswirl/rend/gles/gles.h index 40bcacdd26..74aa788865 100644 --- a/libswirl/rend/gles/gles.h +++ b/libswirl/rend/gles/gles.h @@ -62,12 +62,6 @@ struct gl_ctx std::unordered_map shaders; bool rotate90; - struct - { - GLuint program; - GLuint scale; - } OSD_SHADER; - struct { GLuint geometry,modvols,idxs,idxs2; @@ -120,8 +114,7 @@ struct text_info { }; enum ModifierVolumeMode { Xor, Or, Inclusion, Exclusion, ModeCount }; -void gl_load_osd_resources(); -void gl_free_osd_resources(); + bool ProcessFrame(Renderer* renderer, u8* vram, TA_context* ctx); void UpdateFogTexture(u8 *fog_table, GLenum texture_slot, GLint fog_image_format); @@ -142,8 +135,6 @@ GLuint init_output_framebuffer(int width, int height); bool render_output_framebuffer(); void free_output_framebuffer(); -void HideOSD(); -void OSD_DRAW(bool clear_screen); PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode, u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset, u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear); diff --git a/libswirl/rend/gles/glesrend.cpp b/libswirl/rend/gles/glesrend.cpp index d597332cad..fe15ce1025 100644 --- a/libswirl/rend/gles/glesrend.cpp +++ b/libswirl/rend/gles/glesrend.cpp @@ -347,81 +347,6 @@ void main() \n\ gl_FragColor=vec4(0.0, 0.0, 0.0, sp_ShaderColor); \n\ }"; -const char* OSD_VertexShader = -"\ -%s \n\ -#define TARGET_GL %s \n\ - \n\ -#define GLES2 0 \n\ -#define GLES3 1 \n\ -#define GL2 2 \n\ -#define GL3 3 \n\ - \n\ -#if TARGET_GL == GL2 \n\ -#define highp \n\ -#define lowp \n\ -#define mediump \n\ -#endif \n\ -#if TARGET_GL == GLES2 || TARGET_GL == GL2 \n\ -#define in attribute \n\ -#define out varying \n\ -#endif \n\ - \n\ -uniform highp vec4 scale; \n\ - \n\ -in highp vec4 in_pos; \n\ -in lowp vec4 in_base; \n\ -in mediump vec2 in_uv; \n\ - \n\ -out lowp vec4 vtx_base; \n\ -out mediump vec2 vtx_uv; \n\ - \n\ -void main() \n\ -{ \n\ - vtx_base = in_base; \n\ - vtx_uv = in_uv; \n\ - highp vec4 vpos = in_pos; \n\ - \n\ - vpos.w = 1.0; \n\ - vpos.z = vpos.w; \n\ - vpos.xy = vpos.xy * scale.xy - scale.zw; \n\ - gl_Position = vpos; \n\ -}"; - -const char* OSD_Shader = -"\ -%s \n\ -#define TARGET_GL %s \n\ - \n\ -#define GLES2 0 \n\ -#define GLES3 1 \n\ -#define GL2 2 \n\ -#define GL3 3 \n\ - \n\ -#if TARGET_GL == GL2 \n\ -#define highp \n\ -#define lowp \n\ -#define mediump \n\ -#endif \n\ -#if TARGET_GL != GLES2 && TARGET_GL != GL2 \n\ -out highp vec4 FragColor; \n\ -#define gl_FragColor FragColor \n\ -#else \n\ -#define in varying \n\ -#define texture texture2D \n\ -#endif \n\ - \n\ -in lowp vec4 vtx_base; \n\ -in mediump vec2 vtx_uv; \n\ -/* Vertex input*/ \n\ -uniform sampler2D tex; \n\ -void main() \n\ -{ \n\ - mediump vec2 uv=vtx_uv; \n\ - uv.y=1.0-uv.y; \n\ - gl_FragColor = vtx_base*texture(tex,uv.st); \n\ -}"; - GLCache glcache; gl_ctx gl; @@ -466,7 +391,6 @@ static void gles_term() glcache.DeleteTextures(1, &fogTextureId); fogTextureId = 0; - gl_free_osd_resources(); free_output_framebuffer(); gl_delete_shaders(); @@ -678,40 +602,6 @@ bool CompilePipelineShader( PipelineShader* s) return glIsProgram(s->program)==GL_TRUE; } -GLuint osd_tex; - -void gl_load_osd_resources() -{ - char vshader[8192]; - char fshader[8192]; - - sprintf(vshader, OSD_VertexShader, gl.glsl_version_header, gl.gl_version); - sprintf(fshader, OSD_Shader, gl.glsl_version_header, gl.gl_version); - - gl.OSD_SHADER.program = gl_CompileAndLink(vshader, fshader); - gl.OSD_SHADER.scale = glGetUniformLocation(gl.OSD_SHADER.program, "scale"); - glUniform1i(glGetUniformLocation(gl.OSD_SHADER.program, "tex"), 0); //bind osd texture to slot 0 - -#ifdef _ANDROID - int w, h; - if (osd_tex == 0) - osd_tex = loadPNG(get_readonly_data_path(DATA_PATH "buttons.png"), w, h); -#endif -} - -void gl_free_osd_resources() -{ - if (gl.OSD_SHADER.program != 0) { - glcache.DeleteProgram(gl.OSD_SHADER.program); - gl.OSD_SHADER.program = 0; - } - - if (osd_tex != 0) { - glcache.DeleteTextures(1, &osd_tex); - osd_tex = 0; - } -} - static void create_modvol_shader() { if (gl.modvol_shader.program != 0) @@ -752,8 +642,6 @@ bool gl_create_resources() create_modvol_shader(); - gl_load_osd_resources(); - return true; } @@ -831,186 +719,6 @@ void UpdateFogTexture(u8 *fog_table, GLenum texture_slot, GLint fog_image_format glActiveTexture(GL_TEXTURE0); } - -extern u16 kcode[4]; -extern u8 rt[4],lt[4]; - -#if defined(_ANDROID) -extern float vjoy_pos[14][8]; -#else - -float vjoy_pos[14][8]= -{ - {24+0,24+64,64,64}, //LEFT - {24+64,24+0,64,64}, //UP - {24+128,24+64,64,64}, //RIGHT - {24+64,24+128,64,64}, //DOWN - - {440+0,280+64,64,64}, //X - {440+64,280+0,64,64}, //Y - {440+128,280+64,64,64}, //B - {440+64,280+128,64,64}, //A - - {320-32,360+32,64,64}, //Start - - {440,200,90,64}, //RT - {542,200,90,64}, //LT - - {-24,128+224,128,128}, //ANALOG_RING - {96,320,64,64}, //ANALOG_POINT - {1} -}; -#endif // !_ANDROID - -static List osd_vertices; -static bool osd_vertices_overrun; - -static const float vjoy_sz[2][14] = { - { 64,64,64,64, 64,64,64,64, 64, 90,90, 128, 64 }, - { 64,64,64,64, 64,64,64,64, 64, 64,64, 128, 64 }, -}; - -void HideOSD() -{ - vjoy_pos[13][0] = 0; - vjoy_pos[13][1] = 0; - vjoy_pos[13][2] = 0; - vjoy_pos[13][3] = 0; -} - -static void DrawButton(float* xy, u32 state) -{ - Vertex vtx; - - vtx.z = 1; - - vtx.col[0]=vtx.col[1]=vtx.col[2]=(0x7F-0x40*state/255)*vjoy_pos[13][0]; - - vtx.col[3]=0xA0*vjoy_pos[13][4]; - - vjoy_pos[13][4]+=(vjoy_pos[13][0]-vjoy_pos[13][4])/2; - - - - vtx.x = xy[0]; vtx.y = xy[1]; - vtx.u=xy[4]; vtx.v=xy[5]; - *osd_vertices.Append() = vtx; - - vtx.x = xy[0] + xy[2]; vtx.y = xy[1]; - vtx.u=xy[6]; vtx.v=xy[5]; - *osd_vertices.Append() = vtx; - - vtx.x = xy[0]; vtx.y = xy[1] + xy[3]; - vtx.u=xy[4]; vtx.v=xy[7]; - *osd_vertices.Append() = vtx; - - vtx.x = xy[0] + xy[2]; vtx.y = xy[1] + xy[3]; - vtx.u=xy[6]; vtx.v=xy[7]; - *osd_vertices.Append() = vtx; -} - -static void DrawButton2(float* xy, bool state) { DrawButton(xy,state?0:255); } - -static void osd_gen_vertices() -{ - osd_vertices.Init(ARRAY_SIZE(vjoy_pos) * 4, &osd_vertices_overrun, "OSD vertices"); - DrawButton2(vjoy_pos[0],kcode[0] & DC_DPAD_LEFT); - DrawButton2(vjoy_pos[1],kcode[0] & DC_DPAD_UP); - DrawButton2(vjoy_pos[2],kcode[0] & DC_DPAD_RIGHT); - DrawButton2(vjoy_pos[3],kcode[0] & DC_DPAD_DOWN); - - DrawButton2(vjoy_pos[4],kcode[0] & DC_BTN_X); - DrawButton2(vjoy_pos[5],kcode[0] & DC_BTN_Y); - DrawButton2(vjoy_pos[6],kcode[0] & DC_BTN_B); - DrawButton2(vjoy_pos[7],kcode[0] & DC_BTN_A); - - DrawButton2(vjoy_pos[8],kcode[0] & DC_BTN_START); - - DrawButton(vjoy_pos[9],lt[0]); - - DrawButton(vjoy_pos[10],rt[0]); - - DrawButton2(vjoy_pos[11],1); - DrawButton2(vjoy_pos[12],0); -} - -#define OSD_TEX_W 512 -#define OSD_TEX_H 256 - -void OSD_DRAW(bool clear_screen) -{ -#ifdef _ANDROID - if (osd_tex == 0) - gl_load_osd_resources(); - if (osd_tex != 0) - { - osd_gen_vertices(); - - float u=0; - float v=0; - - for (int i=0;i<13;i++) - { - //umin,vmin,umax,vmax - vjoy_pos[i][4]=(u+1)/OSD_TEX_W; - vjoy_pos[i][5]=(v+1)/OSD_TEX_H; - - vjoy_pos[i][6]=((u+vjoy_sz[0][i]-1))/OSD_TEX_W; - vjoy_pos[i][7]=((v+vjoy_sz[1][i]-1))/OSD_TEX_H; - - u+=vjoy_sz[0][i]; - if (u>=OSD_TEX_W) - { - u-=OSD_TEX_W; - v+=vjoy_sz[1][i]; - } - //v+=vjoy_pos[i][3]; - } - - verify(glIsProgram(gl.OSD_SHADER.program)); - glcache.UseProgram(gl.OSD_SHADER.program); - - float scale_h = screen_height / 480.f; - float offs_x = (screen_width - scale_h * 640.f) / 2.f; - float scale[4]; - scale[0] = 2.f / (screen_width / scale_h); - scale[1]= -2.f / 480.f; - scale[2]= 1.f - 2.f * offs_x / screen_width; - scale[3]= -1.f; - glUniform4fv(gl.OSD_SHADER.scale, 1, scale); - - glActiveTexture(GL_TEXTURE0); - glcache.BindTexture(GL_TEXTURE_2D, osd_tex); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glBufferData(GL_ARRAY_BUFFER, osd_vertices.bytes(), osd_vertices.head(), GL_STREAM_DRAW); glCheck(); - - glcache.Enable(GL_BLEND); - glcache.Disable(GL_DEPTH_TEST); - glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glcache.DepthMask(false); - glcache.DepthFunc(GL_ALWAYS); - - glcache.Disable(GL_CULL_FACE); - glcache.Disable(GL_SCISSOR_TEST); - glViewport(0, 0, screen_width, screen_height); - - if (clear_screen) - { - glcache.ClearColor(0.7f, 0.7f, 0.7f, 1.f); - glClear(GL_COLOR_BUFFER_BIT); - } - int dfa = osd_vertices.used() / 4; - - for (int i = 0; i < dfa; i++) - glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4); - } -#endif - g_GUI->RenderOSD(); -} - bool ProcessFrame(Renderer* renderer, u8* vram, TA_context* ctx) { ctx->rend_inuse.Lock(); @@ -1533,25 +1241,6 @@ struct glesrend final : Renderer bool RenderLastFrame() { return render_output_framebuffer(); } void Present() { os_gl_swap(); glViewport(0, 0, screen_width, screen_height); } - void DrawOSD(bool clear_screen) - { - - if (gl.gl_major >= 3) - glBindVertexArray(gl.vbo.vao); - - glBindBuffer(GL_ARRAY_BUFFER, gl.vbo.geometry); glCheck(); - glEnableVertexAttribArray(VERTEX_POS_ARRAY); - glVertexAttribPointer(VERTEX_POS_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex,x)); - - glEnableVertexAttribArray(VERTEX_COL_BASE_ARRAY); - glVertexAttribPointer(VERTEX_COL_BASE_ARRAY, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex,col)); - - glEnableVertexAttribArray(VERTEX_UV_ARRAY); - glVertexAttribPointer(VERTEX_UV_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex,u)); - - OSD_DRAW(clear_screen); - } - virtual u32 GetTexture(TSP tsp, TCW tcw) { return gl_GetTexture(vram, tsp, tcw); } diff --git a/libswirl/rend/norend/norend.cpp b/libswirl/rend/norend/norend.cpp index b5a9a05fc6..a41e72a0cc 100644 --- a/libswirl/rend/norend/norend.cpp +++ b/libswirl/rend/norend/norend.cpp @@ -15,8 +15,6 @@ struct norend : Renderer bool Process(TA_context* ctx) { return true; } - void DrawOSD() { } - bool RenderPVR() { return true;//!pvrrc.isRTT; From f8a82ffb67b17a981f85be650997884143cad528 Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Fri, 31 Jan 2020 13:37:36 +0200 Subject: [PATCH 3/6] Android: Fix vjoy edit reset crash --- .../java/com/reicast/emulator/NativeGLActivity.java | 13 ++++++++++++- .../emulator/emu/VirtualJoystickDelegate.java | 12 +++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java b/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java index 830aba1acb..c8b488dc23 100644 --- a/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java +++ b/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java @@ -1,6 +1,8 @@ package com.reicast.emulator; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.support.annotation.Nullable; import android.view.ViewGroup; import android.view.Window; @@ -54,7 +56,16 @@ private void VJoyResetEditing() { VJoy.resetCustomVjoyValues(getApplicationContext()); ((NativeGLView)mView).readCustomVjoyValues(); ((NativeGLView)mView).resetEditMode(); - mView.requestLayout(); + + // force re setting of jndidc.vjoy via layout + // *WATCH* we are not in Java UI thread here + + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + mView.requestLayout(); + } + }); } // Called from native code private void VJoyStopEditing(boolean canceled) { diff --git a/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/VirtualJoystickDelegate.java b/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/VirtualJoystickDelegate.java index e3e142adfd..8a3cc906f9 100644 --- a/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/VirtualJoystickDelegate.java +++ b/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/VirtualJoystickDelegate.java @@ -3,6 +3,7 @@ import android.content.Context; import android.content.res.Configuration; import android.os.Handler; +import android.os.Looper; import android.os.Vibrator; import android.view.InputDevice; import android.view.MotionEvent; @@ -56,7 +57,16 @@ public void restoreCustomVjoyValues(float[][] vjoy_d_cached) { VJoy.writeCustomVjoyValues(vjoy_d_cached, context); resetEditMode(); - view.requestLayout(); + + // force re setting of jndidc.vjoy via layout + // *WATCH* we are not in Java UI thread here + + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + view.requestLayout(); + } + }); } From a551178ec7ebf1c4074928228202f99b58d3f24a Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Fri, 31 Jan 2020 13:37:57 +0200 Subject: [PATCH 4/6] libswirl: Fix reboots to actually re-start the cpu --- libswirl/libswirl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libswirl/libswirl.cpp b/libswirl/libswirl.cpp index 7c2334233b..569d84a9fa 100644 --- a/libswirl/libswirl.cpp +++ b/libswirl/libswirl.cpp @@ -718,11 +718,12 @@ struct Dreamcast_impl : VirtualDreamcast { if (reset_requested) { virtualDreamcast->Reset(); + sh4_cpu->Start(); #ifdef SCRIPTING luabindings_onreset(); #endif } - } while (reset_requested); + } while (reset_requested); #ifdef SCRIPTING luabindings_onstop(); From 17c569fac8d77da24c3319127d251c646e0e4f86 Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Fri, 31 Jan 2020 13:55:19 +0200 Subject: [PATCH 5/6] Rend: Call glViewPort now that REND::Resize is used --- libswirl/rend/gl4/gl4rend.cpp | 1 + libswirl/rend/gles/glesrend.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libswirl/rend/gl4/gl4rend.cpp b/libswirl/rend/gl4/gl4rend.cpp index 0e70424dac..ed5c8d02d1 100644 --- a/libswirl/rend/gl4/gl4rend.cpp +++ b/libswirl/rend/gl4/gl4rend.cpp @@ -967,6 +967,7 @@ struct gl4rend : Renderer bool Init() { return (hasInited = gl41_init()); } void Resize(int w, int h) { + glViewport(0, 0, w, h); if (w != old_screen_width || h != old_screen_height || settings.rend.ScreenScaling != old_screen_scaling) { diff --git a/libswirl/rend/gles/glesrend.cpp b/libswirl/rend/gles/glesrend.cpp index fe15ce1025..44e4a0a1b0 100644 --- a/libswirl/rend/gles/glesrend.cpp +++ b/libswirl/rend/gles/glesrend.cpp @@ -1227,7 +1227,9 @@ struct glesrend final : Renderer fb_scale_y = y; } - void Resize(int w, int h) { /* do nothing */ } + void Resize(int w, int h) { + glViewport(0, 0, w, h); + } ~glesrend() { if (wasInit) { From 9ae4bee0390d837726dc0b6589d65bc320d627c4 Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Fri, 31 Jan 2020 15:04:53 +0200 Subject: [PATCH 6/6] sh4: Fix sh4::Stop() if no interrupts are happening --- libswirl/hw/sh4/SuperH4_impl.cpp | 4 +++- libswirl/hw/sh4/interpr/sh4_interpreter.cpp | 15 ++++++++++++--- libswirl/jit/backend/x64/rec_x64.cpp | 1 + 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/libswirl/hw/sh4/SuperH4_impl.cpp b/libswirl/hw/sh4/SuperH4_impl.cpp index 06bcdf4d3e..37c6dd21e9 100644 --- a/libswirl/hw/sh4/SuperH4_impl.cpp +++ b/libswirl/hw/sh4/SuperH4_impl.cpp @@ -17,7 +17,9 @@ int UpdateSystem() if (Sh4cntx.sh4_sched_next < 0) sh4_sched_tick(SH4_TIMESLICE); - return Sh4cntx.interrupt_pend; + // Force an interrupt check if the cpu has been stopped + // ngen is required to only check the bCpuRun on interrupt processing + return Sh4cntx.interrupt_pend | (sh4_int_bCpuRun == false); } int UpdateSystem_INTC() diff --git a/libswirl/hw/sh4/interpr/sh4_interpreter.cpp b/libswirl/hw/sh4/interpr/sh4_interpreter.cpp index 121c1335a6..ade95925ee 100644 --- a/libswirl/hw/sh4/interpr/sh4_interpreter.cpp +++ b/libswirl/hw/sh4/interpr/sh4_interpreter.cpp @@ -5,6 +5,7 @@ #include "types.h" #include "../sh4_interpreter.h" +#include "../sh4_interrupts.h" #include "../sh4_opcode_list.h" #include "../sh4_core.h" #include "hw/sh4/sh4_mem.h" @@ -86,8 +87,17 @@ struct SH4IInterpreter : SuperH4Backend { l -= CPU_RATIO; } while (l > 0); + l += SH4_TIMESLICE; - UpdateSystem_INTC(); + + // model how the jit works + // only check for sh4_int_bCpuRun on interrupts + if (UpdateSystem()) { + UpdateINTC(); + if (!sh4_int_bCpuRun) + break; + } + #if !defined(NO_MMU) } catch (SH4ThrownException& ex) { @@ -95,8 +105,7 @@ struct SH4IInterpreter : SuperH4Backend { l -= CPU_RATIO * 5; // an exception requires the instruction pipeline to drain, so approx 5 cycles } #endif - - } while (sh4_int_bCpuRun); + } while (true); } bool Init() { return true; } diff --git a/libswirl/jit/backend/x64/rec_x64.cpp b/libswirl/jit/backend/x64/rec_x64.cpp index d9f883bca1..d6b17487ff 100644 --- a/libswirl/jit/backend/x64/rec_x64.cpp +++ b/libswirl/jit/backend/x64/rec_x64.cpp @@ -122,6 +122,7 @@ class BlockCompiler : public Xbyak::CodeGenerator emit_Skip(getSize()); } + //TODO: FIXME THIS DOES NOT CONFORM TO NGEN SPEC AROUND INTERRUPT HANDLING void build_mainloop() { Xbyak::Label run_loop, slice_loop, end_loop; // Store callee saved registers (64 bytes) + align stack