From d861e3d47de3848abc63c5e2e000768cd452b6b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sat, 24 Nov 2018 12:41:15 +0700 Subject: [PATCH 01/36] Improve the libretro binding to support GL cores --- core/environment.go | 5 +++++ libretro/cfuncs.go | 12 ++++++++++++ libretro/libretro.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ state/state.go | 1 + 4 files changed, 62 insertions(+) diff --git a/core/environment.go b/core/environment.go index 36d44578..dcefad5c 100644 --- a/core/environment.go +++ b/core/environment.go @@ -1,6 +1,7 @@ package core import ( + "fmt" "log" "os/user" "time" @@ -45,6 +46,10 @@ func environment(cmd uint32, data unsafe.Pointer) bool { state.Global.FrameTimeCb = libretro.SetFrameTimeCallback(data) case libretro.EnvironmentSetAudioCallback: state.Global.AudioCb = libretro.SetAudioCallback(data) + case libretro.EnvironmentSetHWRenderer: + state.Global.HWRenderCb = libretro.SetHWRenderCallback(data) + fmt.Println(state.Global.HWRenderCb) + return true case libretro.EnvironmentGetCanDupe: libretro.SetBool(data, true) case libretro.EnvironmentSetPixelFormat: diff --git a/libretro/cfuncs.go b/libretro/cfuncs.go index 8704039a..0f0ccdd3 100644 --- a/libretro/cfuncs.go +++ b/libretro/cfuncs.go @@ -22,6 +22,18 @@ void bridge_retro_frame_time_callback(retro_frame_time_callback_t f, retro_usec_ f(usec); } +void bridge_retro_hw_context_reset(retro_hw_context_reset_t f) { + f(); +} + +void bridge_retro_hw_context_destroy(retro_hw_context_reset_t f) { + f(); +} + +uintptr_t bridge_retro_hw_get_current_framebuffer(retro_hw_get_current_framebuffer_t f) { + return ((uintptr_t (*)(void))f)(); +} + void bridge_retro_audio_callback(retro_audio_callback_t f) { f(); } diff --git a/libretro/libretro.go b/libretro/libretro.go index 4c9e8e40..81bf9f0c 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -32,6 +32,9 @@ void bridge_retro_unload_game(void *f); void bridge_retro_run(void *f); void bridge_retro_reset(void *f); void bridge_retro_frame_time_callback(retro_frame_time_callback_t f, retro_usec_t usec); +void bridge_retro_hw_context_reset(retro_hw_context_reset_t f); +uintptr_t bridge_retro_hw_get_current_framebuffer(retro_hw_get_current_framebuffer_t f); +void bridge_retro_hw_context_destroy(retro_hw_context_reset_t f); void bridge_retro_audio_callback(retro_audio_callback_t f); void bridge_retro_audio_set_state(retro_audio_set_state_callback_t f, bool state); @@ -121,6 +124,22 @@ type FrameTimeCallback struct { Reference int64 } +// HWRenderCallback sets an interface to let a libretro core render with +// hardware acceleration. +type HWRenderCallback struct { + HWContextType uint + ContextReset func() + GetCurrentFramebuffer func() uintptr + GetProcAddress func() + Depth bool + Stencil bool + BottomLeftOrigin bool + VersionMajor, VersionMinor uint + CacheContext bool + ContextDestroy func() + DebugContext bool +} + // AudioCallback stores the audio callback itself and the SetState callback type AudioCallback struct { Callback func() @@ -179,6 +198,7 @@ const ( EnvironmentGetPerfInterface = uint32(C.RETRO_ENVIRONMENT_GET_PERF_INTERFACE) EnvironmentSetFrameTimeCallback = uint32(C.RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK) EnvironmentSetAudioCallback = uint32(C.RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK) + EnvironmentSetHWRenderer = uint32(C.RETRO_ENVIRONMENT_SET_HW_RENDER) ) // Debug levels @@ -531,6 +551,30 @@ func SetFrameTimeCallback(data unsafe.Pointer) FrameTimeCallback { return ftc } +// SetHWRenderCallback is an environment callback helper to set the HWRenderCallback +func SetHWRenderCallback(data unsafe.Pointer) HWRenderCallback { + c := *(*C.struct_retro_hw_render_callback)(data) + hwrc := HWRenderCallback{} + hwrc.HWContextType = uint(c.context_type) + hwrc.ContextReset = func() { + C.bridge_retro_hw_context_reset(c.context_reset) + } + hwrc.GetCurrentFramebuffer = func() uintptr { + return uintptr(C.bridge_retro_hw_get_current_framebuffer(c.get_current_framebuffer)) + } + hwrc.Depth = bool(c.depth) + hwrc.Stencil = bool(c.stencil) + hwrc.BottomLeftOrigin = bool(c.bottom_left_origin) + hwrc.VersionMajor = uint(c.version_major) + hwrc.VersionMinor = uint(c.version_minor) + hwrc.CacheContext = bool(c.cache_context) + hwrc.ContextDestroy = func() { + C.bridge_retro_hw_context_destroy(c.context_destroy) + } + hwrc.DebugContext = bool(c.debug_context) + return hwrc +} + // SetAudioCallback is an environment callback helper to set the AudioCallback func SetAudioCallback(data unsafe.Pointer) AudioCallback { c := *(*C.struct_retro_audio_callback)(data) diff --git a/state/state.go b/state/state.go index 1688e526..aae975fa 100644 --- a/state/state.go +++ b/state/state.go @@ -12,6 +12,7 @@ type State struct { Core libretro.Core // Current libretro core FrameTimeCb libretro.FrameTimeCallback AudioCb libretro.AudioCallback + HWRenderCb libretro.HWRenderCallback CoreRunning bool MenuActive bool // When set to true, will display the menu layer Verbose bool From 7e794694f52b87b49bc7ceb647c5558e83a42dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 30 Dec 2018 12:33:24 +0700 Subject: [PATCH 02/36] Start implementing InitFramebuffer --- core/core.go | 4 ++++ core/environment.go | 2 ++ libretro/libretro.go | 2 +- video/video.go | 16 ++++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/core/core.go b/core/core.go index 259f154d..57ecdbd6 100644 --- a/core/core.go +++ b/core/core.go @@ -5,6 +5,7 @@ package core import ( "archive/zip" "errors" + "fmt" "io" "log" "os" @@ -154,6 +155,9 @@ func LoadGame(filename string) error { state.Global.MenuActive = false state.Global.GamePath = filename + fmt.Println(vid.Geom.BaseWidth) + vid.InitFramebuffer(vid.Geom.BaseWidth, vid.Geom.BaseHeight) + log.Println("[Core]: Game loaded: " + filename) return nil } diff --git a/core/environment.go b/core/environment.go index dcefad5c..72b8f77f 100644 --- a/core/environment.go +++ b/core/environment.go @@ -48,6 +48,8 @@ func environment(cmd uint32, data unsafe.Pointer) bool { state.Global.AudioCb = libretro.SetAudioCallback(data) case libretro.EnvironmentSetHWRenderer: state.Global.HWRenderCb = libretro.SetHWRenderCallback(data) + state.Global.HWRenderCb.GetCurrentFramebuffer = vid.CurrentFramebuffer + state.Global.HWRenderCb.GetProcAddress = vid.ProcAddress fmt.Println(state.Global.HWRenderCb) return true case libretro.EnvironmentGetCanDupe: diff --git a/libretro/libretro.go b/libretro/libretro.go index 81bf9f0c..44295e11 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -130,7 +130,7 @@ type HWRenderCallback struct { HWContextType uint ContextReset func() GetCurrentFramebuffer func() uintptr - GetProcAddress func() + GetProcAddress func() uintptr Depth bool Stencil bool BottomLeftOrigin bool diff --git a/video/video.go b/video/video.go index 812479cb..42d5d9f0 100644 --- a/video/video.go +++ b/video/video.go @@ -51,6 +51,7 @@ type Video struct { pixFmt uint32 pixType uint32 bpp int32 + fboID uint32 } // Init instanciates the video package @@ -124,6 +125,12 @@ func (video *Video) configureContext() uint { return GLSLVersion } +func (video *Video) InitFramebuffer(width, height int) { + gl.GenFramebuffers(1, &video.fboID) + gl.BindFramebuffer(gl.FRAMEBUFFER, video.fboID) + gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, video.texID, 0) +} + // Configure instanciates the video package func (video *Video) Configure(fullscreen bool) { var width, height int @@ -348,6 +355,15 @@ func (video *Video) Refresh(data unsafe.Pointer, width int32, height int32, pitc } } +// CurrentFramebuffer returns the current FBO ID +func (video *Video) CurrentFramebuffer() uintptr { + return uintptr(video.fboID) +} + +func (video *Video) ProcAddress() uintptr { + return 0 +} + var vertices = []float32{ // X, Y, U, V -1.0, -1.0, 0.0, 1.0, // left-bottom From d41ab5d9d7f86a7dc9ba6c722fcc56b0f47904fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 30 Dec 2018 12:38:54 +0700 Subject: [PATCH 03/36] TODO --- video/video.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/video.go b/video/video.go index 42d5d9f0..63fa66ab 100644 --- a/video/video.go +++ b/video/video.go @@ -361,7 +361,7 @@ func (video *Video) CurrentFramebuffer() uintptr { } func (video *Video) ProcAddress() uintptr { - return 0 + return 0 // TODO find a way to call GetProcAddress from glfw } var vertices = []float32{ From c6c0c9c81939e8b91fd7bbbed33bf83ed1f558a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 30 Dec 2018 13:03:25 +0700 Subject: [PATCH 04/36] Try to implement ProcAddress --- libretro/libretro.go | 2 +- video/video.go | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/libretro/libretro.go b/libretro/libretro.go index 44295e11..77962d3b 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -130,7 +130,7 @@ type HWRenderCallback struct { HWContextType uint ContextReset func() GetCurrentFramebuffer func() uintptr - GetProcAddress func() uintptr + GetProcAddress func(string) uintptr Depth bool Stencil bool BottomLeftOrigin bool diff --git a/video/video.go b/video/video.go index 63fa66ab..0c8b1a44 100644 --- a/video/video.go +++ b/video/video.go @@ -360,8 +360,19 @@ func (video *Video) CurrentFramebuffer() uintptr { return uintptr(video.fboID) } -func (video *Video) ProcAddress() uintptr { - return 0 // TODO find a way to call GetProcAddress from glfw +/* +Added this in glfw context.go + +func GetProcAddress(procName string) uintptr { + p := C.CString(procName) + defer C.free(unsafe.Pointer(p)) + ret := unsafe.Pointer(C.glfwGetProcAddress(p)) + panicError() + return uintptr(ret) +} +*/ +func (video *Video) ProcAddress(procName string) uintptr { + return glfw.GetProcAddress(procName) } var vertices = []float32{ From a7da8f7cb9f53b6e3dddbefa44c6fe1023618ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Fri, 22 Feb 2019 16:18:06 +0700 Subject: [PATCH 05/36] Fix display of non gl cores --- core/core.go | 2 -- video/video.go | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/core/core.go b/core/core.go index 838f21cb..106325d7 100644 --- a/core/core.go +++ b/core/core.go @@ -6,7 +6,6 @@ package core import ( "archive/zip" "errors" - "fmt" "io" "io/ioutil" "log" @@ -184,7 +183,6 @@ func LoadGame(gamePath string) error { ntf.Display(ntf.Info, "Press P to toggle the menu", ntf.Medium) - fmt.Println(vid.Geom.BaseWidth) vid.InitFramebuffer(vid.Geom.BaseWidth, vid.Geom.BaseHeight) return nil diff --git a/video/video.go b/video/video.go index acdbb5f9..ed196652 100644 --- a/video/video.go +++ b/video/video.go @@ -340,6 +340,7 @@ func (video *Video) Render() { // Refresh the texture framebuffer func (video *Video) Refresh(data unsafe.Pointer, width int32, height int32, pitch int32) { + gl.BindFramebuffer(gl.FRAMEBUFFER, 0) gl.BindTexture(gl.TEXTURE_2D, video.texID) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, video.pixType, video.pixFmt, nil) From a7cf8d1f996ea4d4b4ff5726b971a79b0e610f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Fri, 22 Feb 2019 16:27:24 +0700 Subject: [PATCH 06/36] Implement more of InitFramebuffer --- video/video.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/video/video.go b/video/video.go index ed196652..1e513bfe 100644 --- a/video/video.go +++ b/video/video.go @@ -52,6 +52,7 @@ type Video struct { pixType uint32 bpp int32 fboID uint32 + rboID uint32 } // Init instanciates the video package @@ -129,6 +130,37 @@ func (video *Video) InitFramebuffer(width, height int) { gl.GenFramebuffers(1, &video.fboID) gl.BindFramebuffer(gl.FRAMEBUFFER, video.fboID) gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, video.texID, 0) + + hw := state.Global.Core.HWRenderCallback + + if hw != nil { + if hw.Depth && hw.Stencil { + gl.GenRenderbuffers(1, &video.rboID) + gl.BindRenderbuffer(gl.RENDERBUFFER, video.rboID) + gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, int32(width), int32(height)) + + gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, video.rboID) + } else if hw.Depth { + gl.GenRenderbuffers(1, &video.rboID) + gl.BindRenderbuffer(gl.RENDERBUFFER, video.rboID) + gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT24, int32(width), int32(height)) + + gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, video.rboID) + } + + if hw.Depth || hw.Stencil { + gl.BindRenderbuffer(gl.RENDERBUFFER, 0) + } + } + + gl.BindRenderbuffer(gl.RENDERBUFFER, 0) + + //SDL_assert(glCheckFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) + + gl.ClearColor(0, 0, 0, 1) + gl.Clear(gl.COLOR_BUFFER_BIT) + + gl.BindFramebuffer(gl.FRAMEBUFFER, 0) } // Configure instanciates the video package From d3fd407e77727cfe965504d0c75a6c253f1674f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Fri, 22 Feb 2019 16:32:59 +0700 Subject: [PATCH 07/36] Move InitFramebuffer and call HWRenderCallback.ContextReset --- core/core.go | 2 -- video/video.go | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/core.go b/core/core.go index 106325d7..b3a6df34 100644 --- a/core/core.go +++ b/core/core.go @@ -183,8 +183,6 @@ func LoadGame(gamePath string) error { ntf.Display(ntf.Info, "Press P to toggle the menu", ntf.Medium) - vid.InitFramebuffer(vid.Geom.BaseWidth, vid.Geom.BaseHeight) - return nil } diff --git a/video/video.go b/video/video.go index 1e513bfe..ff03bcc9 100644 --- a/video/video.go +++ b/video/video.go @@ -279,6 +279,11 @@ func (video *Video) Configure(fullscreen bool) { gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) video.white = newWhite() + + if state.Global.CoreRunning { + video.InitFramebuffer(video.Geom.BaseWidth, video.Geom.BaseHeight) + state.Global.Core.HWRenderCallback.ContextReset() + } } // SetPixelFormat is a callback passed to the libretro implementation. From 7eef38cf2e67d3830fa710e251b311a402954886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Tue, 12 Mar 2019 19:00:31 +0700 Subject: [PATCH 08/36] Comment --- video/video.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/video/video.go b/video/video.go index e1f45cca..0aa4f1b4 100644 --- a/video/video.go +++ b/video/video.go @@ -128,6 +128,8 @@ func (video *Video) configureContext() uint { return GLSLVersion } +// InitFramebuffer initializes and configures the video frame buffer based on +// informations from the HWRenderCallback of the libretro core. func (video *Video) InitFramebuffer(width, height int) { gl.GenFramebuffers(1, &video.fboID) gl.BindFramebuffer(gl.FRAMEBUFFER, video.fboID) From 87175ca350f9ea9ffc5d8a3b3bb54956a7f518d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Tue, 12 Mar 2019 19:58:20 +0700 Subject: [PATCH 09/36] Call vid.InitFramebuffer and Core.HWRenderCallback.ContextReset during LoadGame --- core/core.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/core.go b/core/core.go index b3a6df34..70d69dc3 100644 --- a/core/core.go +++ b/core/core.go @@ -183,6 +183,9 @@ func LoadGame(gamePath string) error { ntf.Display(ntf.Info, "Press P to toggle the menu", ntf.Medium) + vid.InitFramebuffer(vid.Geom.BaseWidth, vid.Geom.BaseHeight) + state.Global.Core.HWRenderCallback.ContextReset() + return nil } From 6e4b4b634e28072295aef213903dc34d4ddc2563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Tue, 12 Mar 2019 21:32:28 +0700 Subject: [PATCH 10/36] Remove useless code --- libretro/cfuncs.go | 4 ---- libretro/libretro.go | 4 ---- 2 files changed, 8 deletions(-) diff --git a/libretro/cfuncs.go b/libretro/cfuncs.go index 5b2532e4..650c18c2 100644 --- a/libretro/cfuncs.go +++ b/libretro/cfuncs.go @@ -30,10 +30,6 @@ void bridge_retro_hw_context_destroy(retro_hw_context_reset_t f) { f(); } -uintptr_t bridge_retro_hw_get_current_framebuffer(retro_hw_get_current_framebuffer_t f) { - return ((uintptr_t (*)(void))f)(); -} - void bridge_retro_audio_callback(retro_audio_callback_t f) { f(); } diff --git a/libretro/libretro.go b/libretro/libretro.go index f2a4eee2..7b625678 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -34,7 +34,6 @@ void bridge_retro_run(void *f); void bridge_retro_reset(void *f); void bridge_retro_frame_time_callback(retro_frame_time_callback_t f, retro_usec_t usec); void bridge_retro_hw_context_reset(retro_hw_context_reset_t f); -uintptr_t bridge_retro_hw_get_current_framebuffer(retro_hw_get_current_framebuffer_t f); void bridge_retro_hw_context_destroy(retro_hw_context_reset_t f); void bridge_retro_audio_callback(retro_audio_callback_t f); void bridge_retro_audio_set_state(retro_audio_set_state_callback_t f, bool state); @@ -647,9 +646,6 @@ func SetHWRenderCallback(data unsafe.Pointer) *HWRenderCallback { hwrc.ContextReset = func() { C.bridge_retro_hw_context_reset(c.context_reset) } - hwrc.GetCurrentFramebuffer = func() uintptr { - return uintptr(C.bridge_retro_hw_get_current_framebuffer(c.get_current_framebuffer)) - } hwrc.Depth = bool(c.depth) hwrc.Stencil = bool(c.stencil) hwrc.BottomLeftOrigin = bool(c.bottom_left_origin) From f241ef4995127461162b3af1ae1b671a17b08cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Tue, 12 Mar 2019 23:58:12 +0700 Subject: [PATCH 11/36] List hardware contexts in the libretro binding --- core/environment.go | 2 -- libretro/libretro.go | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/environment.go b/core/environment.go index 5124a21d..29c46c77 100644 --- a/core/environment.go +++ b/core/environment.go @@ -1,7 +1,6 @@ package core import ( - "fmt" "log" "os" "os/user" @@ -76,7 +75,6 @@ func environment(cmd uint32, data unsafe.Pointer) bool { state.Global.Core.HWRenderCallback = libretro.SetHWRenderCallback(data) state.Global.Core.HWRenderCallback.GetCurrentFramebuffer = vid.CurrentFramebuffer state.Global.Core.HWRenderCallback.GetProcAddress = vid.ProcAddress - fmt.Println(state.Global.Core.HWRenderCallback) return true case libretro.EnvironmentGetCanDupe: libretro.SetBool(data, true) diff --git a/libretro/libretro.go b/libretro/libretro.go index 7b625678..0e13ec14 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -128,7 +128,7 @@ type FrameTimeCallback struct { // HWRenderCallback sets an interface to let a libretro core render with // hardware acceleration. type HWRenderCallback struct { - HWContextType uint + HWContextType uint32 ContextReset func() GetCurrentFramebuffer func() uintptr GetProcAddress func(string) uintptr @@ -265,6 +265,18 @@ const ( MemoryVideoRAM = uint32(C.RETRO_MEMORY_VIDEO_RAM) ) +// Hardware contexts +const ( + HWContextNone = uint32(C.RETRO_HW_CONTEXT_NONE) + HWContextOpenGL = uint32(C.RETRO_HW_CONTEXT_OPENGL) + HWContextOpenGLES2 = uint32(C.RETRO_HW_CONTEXT_OPENGLES2) + HWContextOpenGLCore = uint32(C.RETRO_HW_CONTEXT_OPENGL_CORE) + HWContextOpenGLES3 = uint32(C.RETRO_HW_CONTEXT_OPENGLES3) + HWContextOpenGLESVersion = uint32(C.RETRO_HW_CONTEXT_OPENGLES_VERSION) + HWContextVulkan = uint32(C.RETRO_HW_CONTEXT_VULKAN) + HWContextDummy = uint32(C.RETRO_HW_CONTEXT_DUMMY) +) + type ( environmentFunc func(uint32, unsafe.Pointer) bool videoRefreshFunc func(unsafe.Pointer, int32, int32, int32) @@ -642,7 +654,7 @@ func (core *Core) SetFrameTimeCallback(data unsafe.Pointer) { func SetHWRenderCallback(data unsafe.Pointer) *HWRenderCallback { c := *(*C.struct_retro_hw_render_callback)(data) hwrc := HWRenderCallback{} - hwrc.HWContextType = uint(c.context_type) + hwrc.HWContextType = uint32(c.context_type) hwrc.ContextReset = func() { C.bridge_retro_hw_context_reset(c.context_reset) } From 933c86b8522302b6987a85d45af783b73af06c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Tue, 8 Oct 2019 10:55:36 +0700 Subject: [PATCH 12/36] Update dependency for GetProcAddress --- Makefile | 2 +- core/core.go | 5 ++++- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 908ea1c1..08772670 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ APP = Ludo BUNDLENAME = $(APP)-$(OS)-$(ARCH)-$(VERSION) -CORES = bluemsx fbneo fceumm gambatte genesis_plus_gx handy mednafen_ngp mednafen_pce_fast mednafen_psx mednafen_saturn mednafen_supergrafx mednafen_vb mednafen_wswan mgba np2kai o2em pcsx_rearmed picodrive pokemini prosystem snes9x stella vecx virtualjaguar +CORES = bluemsx fbneo fceumm gambatte genesis_plus_gx handy mednafen_ngp mednafen_pce_fast mednafen_psx mednafen_saturn mednafen_supergrafx mednafen_vb mednafen_wswan mgba np2kai o2em pcsx_rearmed picodrive pokemini prosystem snes9x stella vecx virtualjaguar ppsspp mednafen_psx_hw parallel_n64 ifeq ($(ARCH), arm) CORES := $(filter-out mednafen_saturn,$(CORES)) diff --git a/core/core.go b/core/core.go index b2d20a5d..3dd461ef 100644 --- a/core/core.go +++ b/core/core.go @@ -176,7 +176,10 @@ func LoadGame(gamePath string) error { ntf.Display(ntf.Info, "Press P to toggle the menu", ntf.Medium) vid.InitFramebuffer(vid.Geom.BaseWidth, vid.Geom.BaseHeight) - state.Global.Core.HWRenderCallback.ContextReset() + + if state.Global.Core.HWRenderCallback != nil { + state.Global.Core.HWRenderCallback.ContextReset() + } return nil } diff --git a/go.mod b/go.mod index 4e408d21..8fbd1c72 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/libretro/ludo -replace github.com/go-gl/glfw => github.com/kivutar/glfw v0.0.0-20191005084155-f62590c2c41c +replace github.com/go-gl/glfw => github.com/kivutar/glfw v0.0.0-20191008030156-cee43cb8f5e6 require ( github.com/cavaliercoder/grab v2.0.0+incompatible diff --git a/go.sum b/go.sum index 753d1eea..7dccb14d 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/kivutar/glfont v0.0.0-20190119064645-3f4c07235fb3 h1:6znfTZG6AjHjvkNjSzCt+xdINmWPLTZXSt4UxYYFbxo= github.com/kivutar/glfont v0.0.0-20190119064645-3f4c07235fb3/go.mod h1:yvRxgIrpErStul4gzj88N+5yL15ze5JUVqk6Ze4mU+I= -github.com/kivutar/glfw v0.0.0-20191005084155-f62590c2c41c h1:J4Y0LGjPE4W1Pa5ASjE5jC6Qdv+lW83LeqkVxmsKfE8= -github.com/kivutar/glfw v0.0.0-20191005084155-f62590c2c41c/go.mod h1:+slYytY+JI/Q/kMyBN7J8ps03jTLgePW+z0YWmLIuXw= +github.com/kivutar/glfw v0.0.0-20191008030156-cee43cb8f5e6 h1:y2Th/hDiDrRPSUjR4IgtxYMmmN5nXb2+RQZv0IF0HYs= +github.com/kivutar/glfw v0.0.0-20191008030156-cee43cb8f5e6/go.mod h1:+slYytY+JI/Q/kMyBN7J8ps03jTLgePW+z0YWmLIuXw= github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4= github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= From 341ad35519ba7f91656481c80526fc990f647b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sat, 26 Oct 2019 17:14:40 +0700 Subject: [PATCH 13/36] Fix framebuffer creation --- core/core.go | 7 +++++++ video/video.go | 13 +++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/core/core.go b/core/core.go index 3dd461ef..3cb4c887 100644 --- a/core/core.go +++ b/core/core.go @@ -13,6 +13,7 @@ import ( "path/filepath" "time" + "github.com/go-gl/gl/all-core/gl" "github.com/libretro/ludo/audio" "github.com/libretro/ludo/input" "github.com/libretro/ludo/libretro" @@ -139,6 +140,12 @@ func LoadGame(gamePath string) error { gi.SetData(bytes) } + glError := gl.GetError() + for glError != 0 { + log.Println("[Video]: GL Error:", glError) + glError = gl.GetError() + } + ok := state.Global.Core.LoadGame(*gi) if !ok { state.Global.CoreRunning = false diff --git a/video/video.go b/video/video.go index 5fac5656..8b41b02b 100644 --- a/video/video.go +++ b/video/video.go @@ -130,8 +130,15 @@ func (video *Video) configureContext() uint { // InitFramebuffer initializes and configures the video frame buffer based on // informations from the HWRenderCallback of the libretro core. func (video *Video) InitFramebuffer(width, height int) { + log.Printf("[Video]: Initializing HW render (%v x %v).\n", width, height) + gl.GenFramebuffers(1, &video.fboID) gl.BindFramebuffer(gl.FRAMEBUFFER, video.fboID) + + gl.GenTextures(1, &video.texID) + gl.BindTexture(gl.TEXTURE_2D, video.texID) + gl.TexStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, int32(width), int32(height)) + gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, video.texID, 0) hw := state.Global.Core.HWRenderCallback @@ -146,7 +153,7 @@ func (video *Video) InitFramebuffer(width, height int) { } else if hw.Depth { gl.GenRenderbuffers(1, &video.rboID) gl.BindRenderbuffer(gl.RENDERBUFFER, video.rboID) - gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT24, int32(width), int32(height)) + gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, int32(width), int32(height)) gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, video.rboID) } @@ -158,7 +165,9 @@ func (video *Video) InitFramebuffer(width, height int) { gl.BindRenderbuffer(gl.RENDERBUFFER, 0) - //SDL_assert(glCheckFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) + if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE { + log.Fatalln("[Video] Framebuffer is not complete.") + } gl.ClearColor(0, 0, 0, 1) gl.Clear(gl.COLOR_BUFFER_BIT) From 4914b1660664b62ed30a7b2d1dea7114bc01cc12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sat, 26 Oct 2019 17:20:20 +0700 Subject: [PATCH 14/36] Fix gl.Clear --- video/video.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/video/video.go b/video/video.go index 8b41b02b..16f243da 100644 --- a/video/video.go +++ b/video/video.go @@ -135,7 +135,7 @@ func (video *Video) InitFramebuffer(width, height int) { gl.GenFramebuffers(1, &video.fboID) gl.BindFramebuffer(gl.FRAMEBUFFER, video.fboID) - gl.GenTextures(1, &video.texID) + //gl.GenTextures(1, &video.texID) gl.BindTexture(gl.TEXTURE_2D, video.texID) gl.TexStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, int32(width), int32(height)) @@ -170,7 +170,13 @@ func (video *Video) InitFramebuffer(width, height int) { } gl.ClearColor(0, 0, 0, 1) - gl.Clear(gl.COLOR_BUFFER_BIT) + if hw.Depth && hw.Stencil { + gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) + } else if hw.Depth { + gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) + } else { + gl.Clear(gl.COLOR_BUFFER_BIT) + } gl.BindFramebuffer(gl.FRAMEBUFFER, 0) } From 466c2ef696ec78d2905bbbbcbf340bb891252937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 27 Oct 2019 11:21:17 +0700 Subject: [PATCH 15/36] Cast C.retro_hw_context_reset_t --- libretro/libretro.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libretro/libretro.go b/libretro/libretro.go index e93e83d9..8f7f17e5 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -670,7 +670,7 @@ func SetHWRenderCallback(data unsafe.Pointer) *HWRenderCallback { hwrc := HWRenderCallback{} hwrc.HWContextType = uint32(c.context_type) hwrc.ContextReset = func() { - C.bridge_retro_hw_context_reset(c.context_reset) + C.bridge_retro_hw_context_reset((C.retro_hw_context_reset_t)(c.context_reset)) } hwrc.Depth = bool(c.depth) hwrc.Stencil = bool(c.stencil) @@ -679,7 +679,7 @@ func SetHWRenderCallback(data unsafe.Pointer) *HWRenderCallback { hwrc.VersionMinor = uint(c.version_minor) hwrc.CacheContext = bool(c.cache_context) hwrc.ContextDestroy = func() { - C.bridge_retro_hw_context_destroy(c.context_destroy) + C.bridge_retro_hw_context_destroy((C.retro_hw_context_reset_t)(c.context_destroy)) } hwrc.DebugContext = bool(c.debug_context) return &hwrc From c7030756e36bcd645a1e9efa14eb5667c9b33f8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 27 Oct 2019 12:31:28 +0700 Subject: [PATCH 16/36] Set c.get_current_framebuffer and c.get_proc_address properly --- core/environment.go | 7 +++-- go.sum | 2 ++ libretro/cfuncs.go | 10 +++++++ libretro/libretro.go | 66 +++++++++++++++++++++++++++++++------------- 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/core/environment.go b/core/environment.go index 67e065b5..b99f0af4 100644 --- a/core/environment.go +++ b/core/environment.go @@ -99,9 +99,10 @@ func environment(cmd uint32, data unsafe.Pointer) bool { case libretro.EnvironmentSetAudioCallback: state.Global.Core.SetAudioCallback(data) case libretro.EnvironmentSetHWRenderer: - state.Global.Core.HWRenderCallback = libretro.SetHWRenderCallback(data) - state.Global.Core.HWRenderCallback.GetCurrentFramebuffer = vid.CurrentFramebuffer - state.Global.Core.HWRenderCallback.GetProcAddress = vid.ProcAddress + state.Global.Core.HWRenderCallback = libretro.SetHWRenderCallback( + data, + vid.CurrentFramebuffer, + vid.ProcAddress) return true case libretro.EnvironmentGetCanDupe: libretro.SetBool(data, true) diff --git a/go.sum b/go.sum index db4f5223..8c197e59 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ github.com/kivutar/glfont v0.0.0-20191022044204-7edbc5f87840 h1:Tc95Zr1ms80dGFr8 github.com/kivutar/glfont v0.0.0-20191022044204-7edbc5f87840/go.mod h1:yvRxgIrpErStul4gzj88N+5yL15ze5JUVqk6Ze4mU+I= github.com/kivutar/glfw v0.0.0-20191005084155-f62590c2c41c h1:J4Y0LGjPE4W1Pa5ASjE5jC6Qdv+lW83LeqkVxmsKfE8= github.com/kivutar/glfw v0.0.0-20191005084155-f62590c2c41c/go.mod h1:+slYytY+JI/Q/kMyBN7J8ps03jTLgePW+z0YWmLIuXw= +github.com/kivutar/glfw v0.0.0-20191008030156-cee43cb8f5e6 h1:y2Th/hDiDrRPSUjR4IgtxYMmmN5nXb2+RQZv0IF0HYs= +github.com/kivutar/glfw v0.0.0-20191008030156-cee43cb8f5e6/go.mod h1:+slYytY+JI/Q/kMyBN7J8ps03jTLgePW+z0YWmLIuXw= github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4= github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/libretro/cfuncs.go b/libretro/cfuncs.go index 650c18c2..c4f40935 100644 --- a/libretro/cfuncs.go +++ b/libretro/cfuncs.go @@ -156,5 +156,15 @@ int64_t coreGetTimeUsec_cgo() { return coreGetTimeUsec(); } +uintptr_t coreGetCurrentFramebuffer_cgo() { + uintptr_t coreGetCurrentFramebuffer(); + return coreGetCurrentFramebuffer(); +} + +uintptr_t coreGetProcAddress_cgo(const char *sym) { + uintptr_t coreGetProcAddress(const char *sym); + return coreGetProcAddress(sym); +} + */ import "C" diff --git a/libretro/libretro.go b/libretro/libretro.go index 8f7f17e5..b499efd8 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -48,9 +48,12 @@ size_t coreAudioSampleBatch_cgo(const int16_t *data, size_t frames); int16_t coreInputState_cgo(unsigned port, unsigned device, unsigned index, unsigned id); void coreLog_cgo(enum retro_log_level level, const char *msg); int64_t coreGetTimeUsec_cgo(); +uintptr_t coreGetCurrentFramebuffer_cgo(); +uintptr_t coreGetProcAddress_cgo(const char *sym); */ import "C" import ( + "fmt" "errors" "strings" "unsafe" @@ -130,8 +133,6 @@ type FrameTimeCallback struct { type HWRenderCallback struct { HWContextType uint32 ContextReset func() - GetCurrentFramebuffer func() uintptr - GetProcAddress func(string) uintptr Depth bool Stencil bool BottomLeftOrigin bool @@ -278,25 +279,29 @@ const ( ) type ( - environmentFunc func(uint32, unsafe.Pointer) bool - videoRefreshFunc func(unsafe.Pointer, int32, int32, int32) - audioSampleFunc func(int16, int16) - audioSampleBatchFunc func([]byte, int32) int32 - inputPollFunc func() - inputStateFunc func(uint, uint32, uint, uint) int16 - logFunc func(uint32, string) - getTimeUsecFunc func() int64 + environmentFunc func(uint32, unsafe.Pointer) bool + videoRefreshFunc func(unsafe.Pointer, int32, int32, int32) + audioSampleFunc func(int16, int16) + audioSampleBatchFunc func([]byte, int32) int32 + inputPollFunc func() + inputStateFunc func(uint, uint32, uint, uint) int16 + logFunc func(uint32, string) + getTimeUsecFunc func() int64 + getCurrentFramebufferFunc func() uintptr + getProcAddressFunc func(string) uintptr ) var ( - environment environmentFunc - videoRefresh videoRefreshFunc - audioSample audioSampleFunc - audioSampleBatch audioSampleBatchFunc - inputPoll inputPollFunc - inputState inputStateFunc - log logFunc - getTimeUsec getTimeUsecFunc + environment environmentFunc + videoRefresh videoRefreshFunc + audioSample audioSampleFunc + audioSampleBatch audioSampleBatchFunc + inputPoll inputPollFunc + inputState inputStateFunc + log logFunc + getTimeUsec getTimeUsecFunc + getCurrentFramebuffer getCurrentFramebufferFunc + getProcAddress getProcAddressFunc ) // Load dynamically loads a libretro core at the given path and returns a Core instance @@ -356,6 +361,8 @@ func (core *Core) Deinit() { inputState = nil log = nil getTimeUsec = nil + getCurrentFramebuffer = nil + getProcAddress = nil } // Run runs the game for one video frame. @@ -578,6 +585,16 @@ func coreGetTimeUsec() C.uint64_t { return C.uint64_t(getTimeUsec()) } +//export coreGetCurrentFramebuffer +func coreGetCurrentFramebuffer() C.uintptr_t { + return C.uintptr_t(getCurrentFramebuffer()) +} + +//export coreGetProcAddress +func coreGetProcAddress(sym *C.char) C.uintptr_t { + return C.uintptr_t(getProcAddress(C.GoString(sym))) +} + // SetData is a setter for the data of a GameInfo type func (gi *GameInfo) SetData(bytes []byte) { cstr := C.CString(string(bytes)) @@ -665,13 +682,24 @@ func (core *Core) SetFrameTimeCallback(data unsafe.Pointer) { } // SetHWRenderCallback is an environment callback helper to set the HWRenderCallback -func SetHWRenderCallback(data unsafe.Pointer) *HWRenderCallback { +func SetHWRenderCallback( + data unsafe.Pointer, + currentFramebuffer getCurrentFramebufferFunc, + procAddress getProcAddressFunc, +) *HWRenderCallback { c := *(*C.struct_retro_hw_render_callback)(data) hwrc := HWRenderCallback{} hwrc.HWContextType = uint32(c.context_type) + + getCurrentFramebuffer = currentFramebuffer + getProcAddress = procAddress + c.get_current_framebuffer = (C.retro_hw_get_current_framebuffer_t)(C.coreGetCurrentFramebuffer_cgo) + c.get_proc_address = (C.retro_hw_get_proc_address_t)(C.coreGetProcAddress_cgo) + hwrc.ContextReset = func() { C.bridge_retro_hw_context_reset((C.retro_hw_context_reset_t)(c.context_reset)) } + hwrc.Depth = bool(c.depth) hwrc.Stencil = bool(c.stencil) hwrc.BottomLeftOrigin = bool(c.bottom_left_origin) From 2d55e97431e625ce24d61a65cf94cf459cd7a5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 27 Oct 2019 12:39:57 +0700 Subject: [PATCH 17/36] Lint fix --- libretro/libretro.go | 1 - 1 file changed, 1 deletion(-) diff --git a/libretro/libretro.go b/libretro/libretro.go index b499efd8..6b6cda45 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -53,7 +53,6 @@ uintptr_t coreGetProcAddress_cgo(const char *sym); */ import "C" import ( - "fmt" "errors" "strings" "unsafe" From ab13ef0ebc34d91ef5aa9833a2027cc3c8d1cd06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Fri, 22 Nov 2019 10:56:19 +0700 Subject: [PATCH 18/36] Fix compat with non GL cores --- core/core.go | 3 +-- video/video.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/core.go b/core/core.go index fde79c7c..42a4287d 100644 --- a/core/core.go +++ b/core/core.go @@ -188,9 +188,8 @@ func LoadGame(gamePath string) error { ntf.Display(ntf.Info, "Press P to toggle the menu", ntf.Medium) - vid.InitFramebuffer(vid.Geom.BaseWidth, vid.Geom.BaseHeight) - if state.Global.Core.HWRenderCallback != nil { + vid.InitFramebuffer(vid.Geom.BaseWidth, vid.Geom.BaseHeight) state.Global.Core.HWRenderCallback.ContextReset() } diff --git a/video/video.go b/video/video.go index f1fad7c2..9d85e4eb 100644 --- a/video/video.go +++ b/video/video.go @@ -282,7 +282,7 @@ func (video *Video) Configure(fullscreen bool) { video.coreRatioViewport(fbw, fbh) - if state.Global.CoreRunning { + if state.Global.CoreRunning && state.Global.Core.HWRenderCallback != nil { video.InitFramebuffer(video.Geom.BaseWidth, video.Geom.BaseHeight) state.Global.Core.HWRenderCallback.ContextReset() } From 05adbe4f6a6a666a16b494edd9555e581a04de62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Fri, 22 Nov 2019 11:11:09 +0700 Subject: [PATCH 19/36] Debug --- core/environment.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/environment.go b/core/environment.go index b99f0af4..7bbd6fb9 100644 --- a/core/environment.go +++ b/core/environment.go @@ -103,6 +103,7 @@ func environment(cmd uint32, data unsafe.Pointer) bool { data, vid.CurrentFramebuffer, vid.ProcAddress) + log.Println("HWContextType:", state.Global.Core.HWRenderCallback.HWContextType) return true case libretro.EnvironmentGetCanDupe: libretro.SetBool(data, true) From d127589d50bcbcb235ab594d6cf817d9b50a7746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Fri, 22 Nov 2019 12:05:28 +0700 Subject: [PATCH 20/36] Fix an important memory bug --- libretro/libretro.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libretro/libretro.go b/libretro/libretro.go index 6b6cda45..51436714 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -686,7 +686,7 @@ func SetHWRenderCallback( currentFramebuffer getCurrentFramebufferFunc, procAddress getProcAddressFunc, ) *HWRenderCallback { - c := *(*C.struct_retro_hw_render_callback)(data) + c := (*C.struct_retro_hw_render_callback)(data) hwrc := HWRenderCallback{} hwrc.HWContextType = uint32(c.context_type) From 2dd915051057931d7bc3938a6e5498c9d1374b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 24 Nov 2019 20:35:25 +0700 Subject: [PATCH 21/36] Various rendering improvements --- libretro/libretro.go | 6 ++++++ video/video.go | 23 ++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/libretro/libretro.go b/libretro/libretro.go index 51436714..b835ebc9 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -277,6 +277,12 @@ const ( HWContextDummy = uint32(C.RETRO_HW_CONTEXT_DUMMY) ) +// Pass this to retro_video_refresh_t if rendering to hardware. +// Passing NULL to retro_video_refresh_t is still a frame dupe as normal. +var ( + HWFrameBufferValid = unsafe.Pointer(C.RETRO_HW_FRAME_BUFFER_VALID) +) + type ( environmentFunc func(uint32, unsafe.Pointer) bool videoRefreshFunc func(unsafe.Pointer, int32, int32, int32) diff --git a/video/video.go b/video/video.go index 9d85e4eb..04143951 100644 --- a/video/video.go +++ b/video/video.go @@ -319,6 +319,7 @@ func (video *Video) UpdateFilter(filter string) { gl.UseProgram(video.program) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("TextureSize\x00")), float32(video.width), float32(video.height)) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("InputSize\x00")), float32(video.width), float32(video.height)) + gl.UseProgram(0) } // SetPixelFormat is a callback passed to the libretro implementation. @@ -425,6 +426,8 @@ func (video *Video) Render() { gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) + + gl.UseProgram(0) } // Refresh the texture framebuffer @@ -433,20 +436,26 @@ func (video *Video) Refresh(data unsafe.Pointer, width int32, height int32, pitc video.width = width video.height = height - video.pitch = pitch + if pitch != video.pitch { + video.pitch = pitch + gl.PixelStorei(gl.UNPACK_ROW_LENGTH, video.pitch/video.bpp) + } + + if data != nil && data != libretro.HWFrameBufferValid { + gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, video.pixType, video.pixFmt, data) + } + + gl.UseProgram(video.program) + + gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, video.texID) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, video.pixType, video.pixFmt, nil) - gl.PixelStorei(gl.UNPACK_ROW_LENGTH, video.pitch/video.bpp) - gl.UseProgram(video.program) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("TextureSize\x00")), float32(width), float32(height)) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("InputSize\x00")), float32(width), float32(height)) - if data == nil { - return - } - gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, video.pixType, video.pixFmt, data) + gl.UseProgram(0) } // CurrentFramebuffer returns the current FBO ID From 9c5c3f596271c48f8f20b299442b4c518c32189e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 24 Nov 2019 20:52:40 +0700 Subject: [PATCH 22/36] Small fix --- video/video.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/video/video.go b/video/video.go index 04143951..eddd75ca 100644 --- a/video/video.go +++ b/video/video.go @@ -436,11 +436,8 @@ func (video *Video) Refresh(data unsafe.Pointer, width int32, height int32, pitc video.width = width video.height = height - - if pitch != video.pitch { - video.pitch = pitch - gl.PixelStorei(gl.UNPACK_ROW_LENGTH, video.pitch/video.bpp) - } + video.pitch = pitch + gl.PixelStorei(gl.UNPACK_ROW_LENGTH, video.pitch/video.bpp) if data != nil && data != libretro.HWFrameBufferValid { gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, video.pixType, video.pixFmt, data) From 42d43d63c3950d00012cc6ee6870bc8b11d7bd0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 24 Nov 2019 20:56:12 +0700 Subject: [PATCH 23/36] Active texture fixes --- video/video.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/video/video.go b/video/video.go index eddd75ca..b1a095c1 100644 --- a/video/video.go +++ b/video/video.go @@ -270,12 +270,11 @@ func (video *Video) Configure(fullscreen bool) { } gl.GenTextures(1, &video.texID) - - gl.ActiveTexture(gl.TEXTURE0) if video.texID == 0 && state.Global.Verbose { - log.Println("[Video]: Failed to create the vid texture") + log.Fatalln("[Video]: Failed to create the vid texture") } + gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, video.texID) video.UpdateFilter(settings.Current.VideoFilter) @@ -295,6 +294,7 @@ func (video *Video) Configure(fullscreen bool) { // UpdateFilter configures the game texture filter and shader. We currently // support 4 modes: nearest, linear, sharp-bilinear and zfast-crt. func (video *Video) UpdateFilter(filter string) { + gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, video.texID) switch filter { case "linear": From b8144699f6ee821651913ac4ca912f66ab55443a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 24 Nov 2019 21:02:46 +0700 Subject: [PATCH 24/36] Unbind vertex array --- video/video.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/video/video.go b/video/video.go index b1a095c1..84ef5398 100644 --- a/video/video.go +++ b/video/video.go @@ -281,13 +281,17 @@ func (video *Video) Configure(fullscreen bool) { video.coreRatioViewport(fbw, fbh) + gl.BindVertexArray(0) + if state.Global.CoreRunning && state.Global.Core.HWRenderCallback != nil { video.InitFramebuffer(video.Geom.BaseWidth, video.Geom.BaseHeight) state.Global.Core.HWRenderCallback.ContextReset() } - if e := gl.GetError(); e != gl.NO_ERROR { + e := gl.GetError() + for e != gl.NO_ERROR { log.Printf("[Video] OpenGL error: %d\n", e) + e = gl.GetError() } } @@ -420,12 +424,13 @@ func (video *Video) Render() { gl.UseProgram(video.program) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("OutputSize\x00")), w, h) - gl.BindVertexArray(video.vao) - + gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, video.texID) gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) + gl.BindVertexArray(video.vao) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) + gl.BindVertexArray(0) gl.UseProgram(0) } From ff9a3c8f4b37ac846d69bf5f8d9bc88e26969634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Thu, 6 Feb 2020 23:50:07 -0300 Subject: [PATCH 25/36] OpenGL core support improvements (#308) * Fix sample batch callback and OpenGL core support * Fix texture/framebuffer allocation and clipping The libretro api requires the framebuffers to be at least as large as max_width/max_height. * Fix context destruction Fixes Flycast --- core/core.go | 2 +- go.mod | 1 + go.sum | 3 ++ libretro/libretro.go | 10 ++++- video/default_vert_shader.go | 4 +- video/shader_utils.go | 12 ++++++ video/video.go | 73 ++++++++++++++++++++++++++++++++---- 7 files changed, 95 insertions(+), 10 deletions(-) diff --git a/core/core.go b/core/core.go index 42a4287d..7214d15d 100644 --- a/core/core.go +++ b/core/core.go @@ -189,7 +189,7 @@ func LoadGame(gamePath string) error { ntf.Display(ntf.Info, "Press P to toggle the menu", ntf.Medium) if state.Global.Core.HWRenderCallback != nil { - vid.InitFramebuffer(vid.Geom.BaseWidth, vid.Geom.BaseHeight) + vid.InitFramebuffer() state.Global.Core.HWRenderCallback.ContextReset() } diff --git a/go.mod b/go.mod index 777d1cc7..d6d06a0b 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/fatih/structs v1.1.0 github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 + github.com/go-gl/mathgl v0.0.0-20190713194549-592312d8590a github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/kivutar/glfont v0.0.0-20191031044325-c308d6367f39 github.com/lucasb-eyer/go-colorful v1.0.2 diff --git a/go.sum b/go.sum index 683f6311..27778f64 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw= github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk= +github.com/go-gl/mathgl v0.0.0-20190713194549-592312d8590a h1:yoAEv7yeWqfL/l9A/J5QOndXIJCldv+uuQB1DSNQbS0= +github.com/go-gl/mathgl v0.0.0-20190713194549-592312d8590a/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/kivutar/glfont v0.0.0-20191031044325-c308d6367f39 h1:s55p6dLs5iEBt1eqUYNTv7OfnBPubli1YnTTp/H3Ov8= @@ -41,6 +43,7 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067 h1:KYGJGHOQy8oSi1fDlSpcZF0+juKwk/hEMv5SiwHogR0= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/mobile v0.0.0-20190607214518-6fa95d984e88 h1:H6DkDrMSuEE2MQR7DgGwkzbXSY1lvMpEN5MDE1bo/5U= diff --git a/libretro/libretro.go b/libretro/libretro.go index b835ebc9..8f198f4b 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -63,6 +63,8 @@ type GameGeometry struct { AspectRatio float64 BaseWidth int BaseHeight int + MaxWidth int + MaxHeight int } // GameInfo stores information about a ROM @@ -414,6 +416,8 @@ func (core *Core) GetSystemAVInfo() SystemAVInfo { AspectRatio: float64(avi.geometry.aspect_ratio), BaseWidth: int(avi.geometry.base_width), BaseHeight: int(avi.geometry.base_height), + MaxWidth: int(avi.geometry.max_width), + MaxHeight: int(avi.geometry.max_height), }, Timing: SystemTiming{ FPS: float64(avi.timing.fps), @@ -571,7 +575,7 @@ func coreAudioSampleBatch(buf unsafe.Pointer, frames C.size_t) C.size_t { if audioSampleBatch == nil { return 0 } - return C.size_t(audioSampleBatch(C.GoBytes(buf, C.int(4*int(frames))), int32(frames))) + return C.size_t(audioSampleBatch(C.GoBytes(buf, C.int(4*int(frames))), int32(frames))) / 4 } //export coreLog @@ -643,6 +647,8 @@ func GetGeometry(data unsafe.Pointer) GameGeometry { AspectRatio: float64(geometry.aspect_ratio), BaseWidth: int(geometry.base_width), BaseHeight: int(geometry.base_height), + MaxWidth: int(geometry.max_width), + MaxHeight: int(geometry.max_height), } } @@ -655,6 +661,8 @@ func GetSystemAVInfo(data unsafe.Pointer) SystemAVInfo { AspectRatio: float64(avi.geometry.aspect_ratio), BaseWidth: int(avi.geometry.base_width), BaseHeight: int(avi.geometry.base_height), + MaxWidth: int(avi.geometry.max_width), + MaxHeight: int(avi.geometry.max_height), }, Timing: SystemTiming{ FPS: float64(avi.timing.fps), diff --git a/video/default_vert_shader.go b/video/default_vert_shader.go index 7ba28e70..2c7e881e 100644 --- a/video/default_vert_shader.go +++ b/video/default_vert_shader.go @@ -19,8 +19,10 @@ COMPAT_ATTRIBUTE vec2 vertTexCoord; COMPAT_VARYING vec2 fragTexCoord; +uniform mat4 MVP; + void main() { fragTexCoord = vertTexCoord; - gl_Position = vec4(vert, 0.0, 1.0); + gl_Position = vec4(vert, 0.0, 1.0) * MVP; } ` + "\x00" diff --git a/video/shader_utils.go b/video/shader_utils.go index b6306ee4..57bc3d49 100644 --- a/video/shader_utils.go +++ b/video/shader_utils.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/go-gl/gl/all-core/gl" + "github.com/go-gl/mathgl/mgl32" ) func newProgram(GLSLVersion uint, vertexShaderSource, fragmentShaderSource string) (uint32, error) { @@ -42,6 +43,17 @@ func newProgram(GLSLVersion uint, vertexShaderSource, fragmentShaderSource strin gl.DeleteShader(vertexShader) gl.DeleteShader(fragmentShader) + // Only the core rendering code uses MVPs so we set it to identity + // to avoid issues with other parts of the program + gl.UseProgram(program) + mvp := gl.GetUniformLocation(program, gl.Str("MVP\x00")) + + if mvp != -1 { + IdentityMatrix := mgl32.Ident4() + gl.UniformMatrix4fv(mvp, 1, false, &IdentityMatrix[0]) + } + gl.UseProgram(0) + return program, nil } diff --git a/video/video.go b/video/video.go index 84ef5398..81f554af 100644 --- a/video/video.go +++ b/video/video.go @@ -12,6 +12,7 @@ import ( "github.com/go-gl/gl/all-core/gl" "github.com/go-gl/glfw/v3.3/glfw" + "github.com/go-gl/mathgl/mgl32" "github.com/kivutar/glfont" "github.com/libretro/ludo/libretro" "github.com/libretro/ludo/settings" @@ -52,6 +53,8 @@ type Video struct { texID uint32 fboID uint32 rboID uint32 + identityMat mgl32.Mat4 // just a cache + orthoMat mgl32.Mat4 pitch int32 // pitch set by the refresh callback pixFmt uint32 // format set by the environment callback @@ -63,6 +66,7 @@ type Video struct { // Init instanciates the video package func Init(fullscreen bool) *Video { vid := &Video{} + vid.identityMat = mgl32.Ident4() vid.Configure(fullscreen) return vid } @@ -70,6 +74,14 @@ func Init(fullscreen bool) *Video { // Reconfigure destroys and recreates the window with new attributes func (video *Video) Reconfigure(fullscreen bool) { if video.Window != nil { + // This is the expected frontend behavior and Flycast requires this + // for fullscreen toggling to work, but ppsspp breaks. OTOH, ppsspp + // breaks in those situations even if we don't call context_destroy + // so ignore it. + hw := state.Global.Core.HWRenderCallback + if state.Global.CoreRunning && hw != nil && hw.ContextDestroy != nil { + state.Global.Core.HWRenderCallback.ContextDestroy() + } video.Window.Destroy() } video.Configure(fullscreen) @@ -95,7 +107,10 @@ func getGLSLVersion() uint { // InitFramebuffer initializes and configures the video frame buffer based on // informations from the HWRenderCallback of the libretro core. -func (video *Video) InitFramebuffer(width, height int) { +func (video *Video) InitFramebuffer() { + width := video.Geom.MaxWidth + height := video.Geom.MaxHeight + log.Printf("[Video]: Initializing HW render (%v x %v).\n", width, height) gl.GenFramebuffers(1, &video.fboID) @@ -107,6 +122,9 @@ func (video *Video) InitFramebuffer(width, height int) { gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, video.texID, 0) + // Default origin is top left + video.orthoMat = mgl32.Ortho2D(-1, 1, -1, 1) + hw := state.Global.Core.HWRenderCallback if hw != nil { @@ -127,6 +145,10 @@ func (video *Video) InitFramebuffer(width, height int) { if hw.Depth || hw.Stencil { gl.BindRenderbuffer(gl.RENDERBUFFER, 0) } + + if hw.BottomLeftOrigin { + video.orthoMat = mgl32.Ortho2D(-1, 1, 1, -1) + } } gl.BindRenderbuffer(gl.RENDERBUFFER, 0) @@ -269,6 +291,11 @@ func (video *Video) Configure(fullscreen bool) { video.bpp = 2 } + if video.Geom.MaxWidth == 0 || video.Geom.MaxHeight == 0 { + video.Geom.MaxWidth = video.Geom.BaseWidth + video.Geom.MaxHeight = video.Geom.BaseHeight + } + gl.GenTextures(1, &video.texID) if video.texID == 0 && state.Global.Verbose { log.Fatalln("[Video]: Failed to create the vid texture") @@ -276,15 +303,16 @@ func (video *Video) Configure(fullscreen bool) { gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, video.texID) + gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, int32(video.Geom.MaxWidth), int32(video.Geom.MaxHeight), 0, video.pixType, video.pixFmt, nil) video.UpdateFilter(settings.Current.VideoFilter) - video.coreRatioViewport(fbw, fbh) + video.coreRatioViewport(fbw, fbh, video.Geom.BaseWidth, video.Geom.BaseHeight) gl.BindVertexArray(0) if state.Global.CoreRunning && state.Global.Core.HWRenderCallback != nil { - video.InitFramebuffer(video.Geom.BaseWidth, video.Geom.BaseHeight) + video.InitFramebuffer() state.Global.Core.HWRenderCallback.ContextReset() } @@ -367,7 +395,7 @@ func (video *Video) ResetPitch() { // coreRatioViewport configures the vertex array to display the game at the center of the window // while preserving the original ascpect ratio of the game or core -func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h float32) { +func (video *Video) coreRatioViewport(fbWidth, fbHeight, clipWidth, clipHeight int) (x, y, w, h float32) { // Scale the content to fit in the viewport. fbw := float32(fbWidth) fbh := float32(fbHeight) @@ -390,6 +418,12 @@ func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h flo y = (fbh - h) / 2 va := video.vertexArray(x, y, w, h, 1.0) + + va[3] = float32(clipHeight) / float32(video.Geom.MaxHeight) + va[10] = float32(clipWidth) / float32(video.Geom.MaxWidth) + va[11] = va[3] + va[14] = va[10] + gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) gl.BufferData(gl.ARRAY_BUFFER, len(va)*4, gl.Ptr(va), gl.STATIC_DRAW) @@ -404,26 +438,49 @@ func (video *Video) ResizeViewport() { // Render the current frame func (video *Video) Render() { + // Render directly to the screen + gl.BindFramebuffer(gl.FRAMEBUFFER, 0) + + // We can't trust the core to leave the OpenGL in the same state as + // before retro_run() was called so we restore some state manually. + gl.Disable(gl.DEPTH_TEST) + gl.Disable(gl.CULL_FACE) + gl.Disable(gl.DITHER) + gl.Disable(gl.STENCIL_TEST) + gl.Disable(gl.BLEND) + gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) + gl.BlendEquation(gl.FUNC_ADD) + + // The next line might be necessary, but doesn't work in core contexts + // gl.Enable(gl.TEXTURE_2D) + + video.ResizeViewport() + if !state.Global.CoreRunning { gl.ClearColor(1, 1, 1, 1) gl.Clear(gl.COLOR_BUFFER_BIT) return } + gl.ClearColor(0, 0, 0, 1) gl.Clear(gl.COLOR_BUFFER_BIT) // Early return to not render the first frame of a newly loaded game with the // previous game pitch. A sane pitch must be set by video.Refresh first. - if video.pitch == 0 { + if state.Global.Core.HWRenderCallback == nil && video.pitch == 0 { return } fbw, fbh := video.Window.GetFramebufferSize() - _, _, w, h := video.coreRatioViewport(fbw, fbh) + _, _, w, h := video.coreRatioViewport(fbw, fbh, int(video.width), int(video.height)) gl.UseProgram(video.program) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("OutputSize\x00")), w, h) + if state.Global.Core.HWRenderCallback != nil { + gl.UniformMatrix4fv(gl.GetUniformLocation(video.program, gl.Str("MVP\x00")), 1, false, &video.orthoMat[0]) + } + gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, video.texID) gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) @@ -432,6 +489,8 @@ func (video *Video) Render() { gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) gl.BindVertexArray(0) + // Reset MVP to identity to avoid menu issues + gl.UniformMatrix4fv(gl.GetUniformLocation(video.program, gl.Str("MVP\x00")), 1, false, &video.identityMat[0]) gl.UseProgram(0) } @@ -452,7 +511,7 @@ func (video *Video) Refresh(data unsafe.Pointer, width int32, height int32, pitc gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, video.texID) - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, video.pixType, video.pixFmt, nil) + gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, int32(video.Geom.MaxWidth), int32(video.Geom.MaxHeight), 0, video.pixType, video.pixFmt, nil) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("TextureSize\x00")), float32(width), float32(height)) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("InputSize\x00")), float32(width), float32(height)) From 827ae5461db7bdd8488122e1fbdfac5bcc755a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Sun, 23 Feb 2020 18:23:24 -0300 Subject: [PATCH 26/36] Fix sharp-bilinear and zfast-crt filters (#311) TextureSize uniform was receiving the input size instead of the actual texture size. --- video/video.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/video.go b/video/video.go index 37a03164..422f33c3 100644 --- a/video/video.go +++ b/video/video.go @@ -523,7 +523,7 @@ func (video *Video) Refresh(data unsafe.Pointer, width int32, height int32, pitc gl.BindTexture(gl.TEXTURE_2D, video.texID) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, int32(video.Geom.MaxWidth), int32(video.Geom.MaxHeight), 0, video.pixType, video.pixFmt, nil) - gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("TextureSize\x00")), float32(width), float32(height)) + gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("TextureSize\x00")), float32(video.Geom.MaxWidth), float32(video.Geom.MaxHeight)) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("InputSize\x00")), float32(width), float32(height)) gl.UseProgram(0) From f32af42ba9ba70daf2f74059df2d672c5100e58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Mon, 24 Feb 2020 18:42:12 +0700 Subject: [PATCH 27/36] Call gl.TexSubImage2D after binding the texture --- video/video.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/video/video.go b/video/video.go index 422f33c3..0be60a25 100644 --- a/video/video.go +++ b/video/video.go @@ -513,14 +513,15 @@ func (video *Video) Refresh(data unsafe.Pointer, width int32, height int32, pitc video.pitch = pitch gl.PixelStorei(gl.UNPACK_ROW_LENGTH, video.pitch/video.bpp) - if data != nil && data != libretro.HWFrameBufferValid { - gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, video.pixType, video.pixFmt, data) - } - gl.UseProgram(video.program) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, video.texID) + + if data != nil && data != libretro.HWFrameBufferValid { + gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, video.pixType, video.pixFmt, data) + } + gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, int32(video.Geom.MaxWidth), int32(video.Geom.MaxHeight), 0, video.pixType, video.pixFmt, nil) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("TextureSize\x00")), float32(video.Geom.MaxWidth), float32(video.Geom.MaxHeight)) From e35cba220c991f50259694c83aa37fb2ef9d1525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Mon, 24 Feb 2020 18:56:29 +0700 Subject: [PATCH 28/36] Fix shader live update --- video/video.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/video.go b/video/video.go index 0be60a25..d5fcbc1b 100644 --- a/video/video.go +++ b/video/video.go @@ -352,7 +352,7 @@ func (video *Video) UpdateFilter(filter string) { gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.UseProgram(video.program) - gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("TextureSize\x00")), float32(video.width), float32(video.height)) + gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("TextureSize\x00")), float32(video.Geom.MaxWidth), float32(video.Geom.MaxHeight)) gl.Uniform2f(gl.GetUniformLocation(video.program, gl.Str("InputSize\x00")), float32(video.width), float32(video.height)) gl.UseProgram(0) } From dbfbe3ace514cf5fb606044c76d6c39d4e299903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Mon, 24 Feb 2020 19:25:28 +0700 Subject: [PATCH 29/36] Temporarily fix tests --- core/core.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/core/core.go b/core/core.go index cc99e443..b408e55e 100644 --- a/core/core.go +++ b/core/core.go @@ -13,7 +13,6 @@ import ( "path/filepath" "time" - "github.com/go-gl/gl/all-core/gl" "github.com/libretro/ludo/audio" "github.com/libretro/ludo/input" "github.com/libretro/ludo/libretro" @@ -156,11 +155,11 @@ func LoadGame(gamePath string) error { } } - glError := gl.GetError() - for glError != 0 { - log.Println("[Video]: GL Error:", glError) - glError = gl.GetError() - } + // glError := gl.GetError() + // for glError != 0 { + // log.Println("[Video]: GL Error:", glError) + // glError = gl.GetError() + // } ok := state.Global.Core.LoadGame(*gi) if !ok { From 008a70c8511967405bae2e09a032dd0e7dc97d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sat, 29 Feb 2020 15:40:18 +0700 Subject: [PATCH 30/36] Fix FBO on OSX (#313) * Fix FBO on OSX * Remove useless code * Use GL v2.1 for fonts drawing * Fix fonts on OSX with GL 2.1 * Rename * Same thing for GenVertexArrays * Make fl0w work on OSX --- core/core.go | 6 --- menu/thumbnail.go | 2 +- video/font.go | 52 +++++++++---------- video/font_frag_shader.go | 11 ++-- video/gfx.go | 18 +++---- video/screenshot.go | 4 +- video/shader_utils.go | 2 +- video/video.go | 104 ++++---------------------------------- video/video_darwin.go | 78 ++++++++++++++++++++++++++++ video/video_notdarwin.go | 79 +++++++++++++++++++++++++++++ 10 files changed, 209 insertions(+), 147 deletions(-) create mode 100644 video/video_darwin.go create mode 100644 video/video_notdarwin.go diff --git a/core/core.go b/core/core.go index 8e855a6c..06ef511e 100644 --- a/core/core.go +++ b/core/core.go @@ -164,12 +164,6 @@ func LoadGame(gamePath string) error { } } - // glError := gl.GetError() - // for glError != 0 { - // log.Println("[Video]: GL Error:", glError) - // glError = gl.GetError() - // } - ok := state.Global.Core.LoadGame(*gi) if !ok { state.Global.CoreRunning = false diff --git a/menu/thumbnail.go b/menu/thumbnail.go index 45ef5fd8..a97c8836 100644 --- a/menu/thumbnail.go +++ b/menu/thumbnail.go @@ -7,7 +7,7 @@ import ( "path/filepath" "strings" - "github.com/go-gl/gl/all-core/gl" + "github.com/go-gl/gl/v2.1/gl" "github.com/libretro/ludo/settings" "github.com/libretro/ludo/video" ) diff --git a/video/font.go b/video/font.go index f9d0228c..ff45dfc5 100644 --- a/video/font.go +++ b/video/font.go @@ -8,7 +8,7 @@ import ( "io/ioutil" "os" - "github.com/go-gl/gl/all-core/gl" + "github.com/go-gl/gl/v2.1/gl" "github.com/golang/freetype" "github.com/golang/freetype/truetype" "golang.org/x/image/font" @@ -174,22 +174,14 @@ func LoadTrueTypeFont(program uint32, r io.Reader, scale int32, low, high rune, f.fontChar = append(f.fontChar, char) } - // Generate texture - gl.GenTextures(1, &f.textureID) - gl.BindTexture(gl.TEXTURE_2D, f.textureID) - gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) - - gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Dx()), int32(rgba.Rect.Dy()), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix)) - - gl.GenerateMipmap(gl.TEXTURE_2D) - gl.BindTexture(gl.TEXTURE_2D, 0) + textureUniform := gl.GetUniformLocation(f.program, gl.Str("Texture\x00")) + gl.Uniform1i(textureUniform, 0) // Configure VAO/VBO for texture quads - gl.GenVertexArrays(1, &f.vao) + genVertexArrays(1, &f.vao) + bindVertexArray(f.vao) + gl.GenBuffers(1, &f.vbo) - gl.BindVertexArray(f.vao) gl.BindBuffer(gl.ARRAY_BUFFER, f.vbo) vertAttrib := uint32(gl.GetAttribLocation(f.program, gl.Str("vert\x00"))) @@ -200,8 +192,18 @@ func LoadTrueTypeFont(program uint32, r io.Reader, scale int32, low, high rune, gl.EnableVertexAttribArray(texCoordAttrib) gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, false, 4*4, gl.PtrOffset(2*4)) + // Generate texture + gl.ActiveTexture(gl.TEXTURE0) + gl.GenTextures(1, &f.textureID) + gl.BindTexture(gl.TEXTURE_2D, f.textureID) + gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) + gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Dx()), int32(rgba.Rect.Dy()), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix)) + gl.GenerateMipmap(gl.TEXTURE_2D) + gl.BindBuffer(gl.ARRAY_BUFFER, 0) - gl.BindVertexArray(0) + bindVertexArray(0) return f, nil } @@ -224,8 +226,7 @@ func LoadFont(file string, scale int32, windowWidth int, windowHeight int, GLSLV gl.UseProgram(program) // Set screen resolution - resUniform := gl.GetUniformLocation(program, gl.Str("resolution\x00")) - gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight)) + gl.Uniform2f(gl.GetUniformLocation(program, gl.Str("resolution\x00")), float32(windowWidth), float32(windowHeight)) return LoadTrueTypeFont(program, fd, scale, 32, 256, LeftToRight) } @@ -256,15 +257,6 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ lowChar := rune(32) - // Setup blending mode - gl.Enable(gl.BLEND) - gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) - - // Activate corresponding render state - gl.UseProgram(f.program) - // Set text color - gl.Uniform4f(gl.GetUniformLocation(f.program, gl.Str("textColor\x00")), f.color.R, f.color.G, f.color.B, f.color.A) - var coords []point // Iterate through all characters in string @@ -305,13 +297,17 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ x += float32((ch.advance >> 6)) * scale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) } - gl.BindVertexArray(f.vao) + gl.UseProgram(f.program) + gl.Uniform4f(gl.GetUniformLocation(f.program, gl.Str("color\x00")), f.color.R, f.color.G, f.color.B, f.color.A) + gl.Enable(gl.BLEND) + gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) + bindVertexArray(f.vao) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, f.textureID) gl.BindBuffer(gl.ARRAY_BUFFER, f.vbo) gl.BufferData(gl.ARRAY_BUFFER, len(coords)*16, gl.Ptr(coords), gl.DYNAMIC_DRAW) gl.DrawArrays(gl.TRIANGLES, 0, int32(len(coords))) - gl.BindVertexArray(0) + bindVertexArray(0) gl.BindTexture(gl.TEXTURE_2D, 0) gl.UseProgram(0) gl.Disable(gl.BLEND) diff --git a/video/font_frag_shader.go b/video/font_frag_shader.go index fedf344b..30f9f4ea 100644 --- a/video/font_frag_shader.go +++ b/video/font_frag_shader.go @@ -6,7 +6,7 @@ var fontFragmentShader = ` #define COMPAT_ATTRIBUTE in #define COMPAT_TEXTURE texture #define COMPAT_FRAGCOLOR FragColor -out vec4 FragColor; +out vec4 COMPAT_FRAGCOLOR; #else #define COMPAT_VARYING varying #define COMPAT_ATTRIBUTE attribute @@ -14,12 +14,13 @@ out vec4 FragColor; #define COMPAT_FRAGCOLOR gl_FragColor #endif -uniform sampler2D tex; -uniform vec4 textColor; +uniform sampler2D Texture; +uniform vec4 color; + COMPAT_VARYING vec2 fragTexCoord; void main() { - vec4 sampled = vec4(1.0, 1.0, 1.0, COMPAT_TEXTURE(tex, fragTexCoord).r); - COMPAT_FRAGCOLOR = min(textColor, vec4(1.0, 1.0, 1.0, 1.0)) * sampled; + vec4 sampled = vec4(1.0, 1.0, 1.0, COMPAT_TEXTURE(Texture, fragTexCoord).r); + COMPAT_FRAGCOLOR = min(color, vec4(1.0, 1.0, 1.0, 1.0)) * sampled; } ` + "\x00" diff --git a/video/gfx.go b/video/gfx.go index b0e56d08..d1fe2d31 100644 --- a/video/gfx.go +++ b/video/gfx.go @@ -5,7 +5,7 @@ import ( "image/draw" "os" - "github.com/go-gl/gl/all-core/gl" + "github.com/go-gl/gl/v2.1/gl" ) // Color is an RGBA type that we use in the menu @@ -68,13 +68,13 @@ func (video *Video) DrawImage(image uint32, x, y, w, h float32, scale float32, c gl.Uniform4f(gl.GetUniformLocation(video.demulProgram, gl.Str("color\x00")), c.R, c.G, c.B, c.A) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) - gl.BindVertexArray(video.vao) + bindVertexArray(video.vao) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, image) gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) gl.BufferData(gl.ARRAY_BUFFER, len(va)*4, gl.Ptr(va), gl.STATIC_DRAW) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) - gl.BindVertexArray(0) + bindVertexArray(0) gl.BindTexture(gl.TEXTURE_2D, 0) gl.UseProgram(0) gl.Disable(gl.BLEND) @@ -121,11 +121,11 @@ func (video *Video) DrawBorder(x, y, w, h, borderWidth float32, c Color) { gl.Uniform2f(gl.GetUniformLocation(video.borderProgram, gl.Str("size\x00")), w, h) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) - gl.BindVertexArray(video.vao) + bindVertexArray(video.vao) gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) gl.BufferData(gl.ARRAY_BUFFER, len(va)*4, gl.Ptr(va), gl.STATIC_DRAW) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) - gl.BindVertexArray(0) + bindVertexArray(0) gl.UseProgram(0) gl.Disable(gl.BLEND) } @@ -141,11 +141,11 @@ func (video *Video) DrawRect(x, y, w, h, r float32, c Color) { gl.Uniform2f(gl.GetUniformLocation(video.roundedProgram, gl.Str("size\x00")), w, h) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) - gl.BindVertexArray(video.vao) + bindVertexArray(video.vao) gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) gl.BufferData(gl.ARRAY_BUFFER, len(va)*4, gl.Ptr(va), gl.STATIC_DRAW) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) - gl.BindVertexArray(0) + bindVertexArray(0) gl.UseProgram(0) gl.Disable(gl.BLEND) } @@ -160,11 +160,11 @@ func (video *Video) DrawCircle(x, y, r float32, c Color) { gl.Uniform1f(gl.GetUniformLocation(video.circleProgram, gl.Str("radius\x00")), r) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) - gl.BindVertexArray(video.vao) + bindVertexArray(video.vao) gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) gl.BufferData(gl.ARRAY_BUFFER, len(va)*4, gl.Ptr(va), gl.STATIC_DRAW) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) - gl.BindVertexArray(0) + bindVertexArray(0) gl.UseProgram(0) gl.Disable(gl.BLEND) } diff --git a/video/screenshot.go b/video/screenshot.go index 5f35a495..9b765375 100644 --- a/video/screenshot.go +++ b/video/screenshot.go @@ -7,7 +7,7 @@ import ( "path/filepath" "github.com/disintegration/imaging" - "github.com/go-gl/gl/all-core/gl" + "github.com/go-gl/gl/v2.1/gl" "github.com/libretro/ludo/settings" "github.com/libretro/ludo/state" @@ -21,7 +21,7 @@ func (video *Video) renderScreenshot() { gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) gl.BufferData(gl.ARRAY_BUFFER, len(va)*4, gl.Ptr(va), gl.STATIC_DRAW) - gl.BindVertexArray(video.vao) + bindVertexArray(video.vao) gl.BindTexture(gl.TEXTURE_2D, video.texID) gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) diff --git a/video/shader_utils.go b/video/shader_utils.go index 57bc3d49..a1c939f2 100644 --- a/video/shader_utils.go +++ b/video/shader_utils.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/go-gl/gl/all-core/gl" + "github.com/go-gl/gl/v2.1/gl" "github.com/go-gl/mathgl/mgl32" ) diff --git a/video/video.go b/video/video.go index 969f3824..58908f9f 100644 --- a/video/video.go +++ b/video/video.go @@ -5,12 +5,11 @@ package video import ( "log" - "runtime" "strconv" "strings" "unsafe" - "github.com/go-gl/gl/all-core/gl" + "github.com/go-gl/gl/v2.1/gl" "github.com/go-gl/glfw/v3.3/glfw" "github.com/go-gl/mathgl/mgl32" "github.com/libretro/ludo/libretro" @@ -105,70 +104,6 @@ func getGLSLVersion() uint { return uint(v) } -// InitFramebuffer initializes and configures the video frame buffer based on -// informations from the HWRenderCallback of the libretro core. -func (video *Video) InitFramebuffer() { - width := video.Geom.MaxWidth - height := video.Geom.MaxHeight - - log.Printf("[Video]: Initializing HW render (%v x %v).\n", width, height) - - gl.GenFramebuffers(1, &video.fboID) - gl.BindFramebuffer(gl.FRAMEBUFFER, video.fboID) - - //gl.GenTextures(1, &video.texID) - gl.BindTexture(gl.TEXTURE_2D, video.texID) - gl.TexStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, int32(width), int32(height)) - - gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, video.texID, 0) - - // Default origin is top left - video.orthoMat = mgl32.Ortho2D(-1, 1, -1, 1) - - hw := state.Global.Core.HWRenderCallback - - if hw != nil { - if hw.Depth && hw.Stencil { - gl.GenRenderbuffers(1, &video.rboID) - gl.BindRenderbuffer(gl.RENDERBUFFER, video.rboID) - gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, int32(width), int32(height)) - - gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, video.rboID) - } else if hw.Depth { - gl.GenRenderbuffers(1, &video.rboID) - gl.BindRenderbuffer(gl.RENDERBUFFER, video.rboID) - gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, int32(width), int32(height)) - - gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, video.rboID) - } - - if hw.Depth || hw.Stencil { - gl.BindRenderbuffer(gl.RENDERBUFFER, 0) - } - - if hw.BottomLeftOrigin { - video.orthoMat = mgl32.Ortho2D(-1, 1, 1, -1) - } - } - - gl.BindRenderbuffer(gl.RENDERBUFFER, 0) - - if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE { - log.Fatalln("[Video] Framebuffer is not complete.") - } - - gl.ClearColor(0, 0, 0, 1) - if hw.Depth && hw.Stencil { - gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) - } else if hw.Depth { - gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) - } else { - gl.Clear(gl.COLOR_BUFFER_BIT) - } - - gl.BindFramebuffer(gl.FRAMEBUFFER, 0) -} - // Configure instanciates the video package func (video *Video) Configure(fullscreen bool) { var width, height int @@ -184,20 +119,6 @@ func (video *Video) Configure(fullscreen bool) { height = 180 * 3 } - // On OSX we have to force a core profile to not end up with 2.1 which cause - // a font drawing issue - if runtime.GOOS == "darwin" { - glfw.WindowHint(glfw.ContextVersionMajor, 3) - glfw.WindowHint(glfw.ContextVersionMinor, 2) - glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) - glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True) - } else { - glfw.WindowHint(glfw.ContextVersionMajor, 2) - glfw.WindowHint(glfw.ContextVersionMinor, 1) - glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLAnyProfile) - glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.False) - } - var err error video.Window = glfw.CreateWindow(width, height, "Ludo", m, nil) if video.Window == nil { @@ -269,8 +190,8 @@ func (video *Video) Configure(fullscreen bool) { gl.Uniform1i(textureUniform, 0) // Configure the vertex data - gl.GenVertexArrays(1, &video.vao) - gl.BindVertexArray(video.vao) + genVertexArrays(1, &video.vao) + bindVertexArray(video.vao) gl.GenBuffers(1, &video.vbo) gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) @@ -309,17 +230,10 @@ func (video *Video) Configure(fullscreen bool) { video.coreRatioViewport(fbw, fbh, video.Geom.BaseWidth, video.Geom.BaseHeight) - gl.BindVertexArray(0) - - if state.Global.CoreRunning && state.Global.Core.HWRenderCallback != nil { - video.InitFramebuffer() - state.Global.Core.HWRenderCallback.ContextReset() - } + bindVertexArray(0) - e := gl.GetError() - for e != gl.NO_ERROR { + for e := gl.GetError(); e != gl.NO_ERROR; e = gl.NO_ERROR { log.Printf("[Video] OpenGL error: %d\n", e) - e = gl.GetError() } } @@ -452,7 +366,7 @@ func (video *Video) ResizeViewport() { // Render the current frame func (video *Video) Render() { // Render directly to the screen - gl.BindFramebuffer(gl.FRAMEBUFFER, 0) + bindBackbuffer() // We can't trust the core to leave the OpenGL in the same state as // before retro_run() was called so we restore some state manually. @@ -498,9 +412,9 @@ func (video *Video) Render() { gl.BindTexture(gl.TEXTURE_2D, video.texID) gl.BindBuffer(gl.ARRAY_BUFFER, video.vbo) - gl.BindVertexArray(video.vao) + bindVertexArray(video.vao) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) - gl.BindVertexArray(0) + bindVertexArray(0) // Reset MVP to identity to avoid menu issues gl.UniformMatrix4fv(gl.GetUniformLocation(video.program, gl.Str("MVP\x00")), 1, false, &video.identityMat[0]) @@ -509,7 +423,7 @@ func (video *Video) Render() { // Refresh the texture framebuffer func (video *Video) Refresh(data unsafe.Pointer, width int32, height int32, pitch int32) { - gl.BindFramebuffer(gl.FRAMEBUFFER, 0) + bindBackbuffer() video.width = width video.height = height diff --git a/video/video_darwin.go b/video/video_darwin.go new file mode 100644 index 00000000..0ef77ea2 --- /dev/null +++ b/video/video_darwin.go @@ -0,0 +1,78 @@ +// +build darwin + +package video + +import ( + "log" + + "github.com/go-gl/gl/v2.1/gl" + "github.com/go-gl/mathgl/mgl32" + "github.com/libretro/ludo/state" +) + +// InitFramebuffer initializes and configures the video frame buffer based on +// informations from the HWRenderCallback of the libretro core. +func (video *Video) InitFramebuffer() { + width := int32(video.Geom.MaxWidth) + height := int32(video.Geom.MaxHeight) + + log.Printf("[Video]: Initializing HW render (%v x %v).\n", width, height) + + gl.ActiveTexture(gl.TEXTURE0) + gl.BindTexture(gl.TEXTURE_2D, video.texID) + gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, video.pixType, video.pixFmt, nil) + + gl.GenFramebuffersEXT(1, &video.fboID) + gl.BindFramebufferEXT(gl.FRAMEBUFFER_EXT, video.fboID) + gl.FramebufferTexture2DEXT(gl.FRAMEBUFFER_EXT, gl.COLOR_ATTACHMENT0_EXT, gl.TEXTURE_2D, video.texID, 0) + + hw := state.Global.Core.HWRenderCallback + if hw.Depth { + gl.GenRenderbuffersEXT(1, &video.rboID) + gl.BindRenderbufferEXT(gl.RENDERBUFFER_EXT, video.rboID) + format := gl.DEPTH_COMPONENT16 + if hw.Stencil { + format = gl.DEPTH24_STENCIL8_EXT + } + gl.RenderbufferStorageEXT(gl.RENDERBUFFER_EXT, uint32(format), width, height) + gl.BindRenderbufferEXT(gl.RENDERBUFFER_EXT, 0) + + gl.FramebufferRenderbufferEXT(gl.FRAMEBUFFER_EXT, gl.DEPTH_ATTACHMENT_EXT, gl.RENDERBUFFER_EXT, video.rboID) + if hw.Stencil { + gl.FramebufferRenderbufferEXT(gl.FRAMEBUFFER_EXT, gl.STENCIL_ATTACHMENT_EXT, gl.RENDERBUFFER_EXT, video.rboID) + } + } + + // Default origin is top left + video.orthoMat = mgl32.Ortho2D(-1, 1, -1, 1) + if hw.BottomLeftOrigin { + video.orthoMat = mgl32.Ortho2D(-1, 1, 1, -1) + } + + if st := gl.CheckFramebufferStatusEXT(gl.FRAMEBUFFER_EXT); st != gl.FRAMEBUFFER_COMPLETE_EXT { + log.Fatalf("[Video] Framebuffer is not complete. Error: %v\n", st) + } + + bindBackbuffer() + + gl.ClearColor(0, 0, 0, 1) + if hw.Depth && hw.Stencil { + gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) + } else if hw.Depth { + gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) + } else { + gl.Clear(gl.COLOR_BUFFER_BIT) + } +} + +func bindBackbuffer() { + gl.BindFramebufferEXT(gl.FRAMEBUFFER_EXT, 0) +} + +func genVertexArrays(n int32, arrays *uint32) { + gl.GenVertexArraysAPPLE(n, arrays) +} + +func bindVertexArray(array uint32) { + gl.BindVertexArrayAPPLE(array) +} diff --git a/video/video_notdarwin.go b/video/video_notdarwin.go new file mode 100644 index 00000000..6e676f18 --- /dev/null +++ b/video/video_notdarwin.go @@ -0,0 +1,79 @@ +// +build !darwin + +package video + +import ( + "log" + + "github.com/go-gl/gl/v2.1/gl" + "github.com/go-gl/mathgl/mgl32" + "github.com/libretro/ludo/state" +) + +// InitFramebuffer initializes and configures the video frame buffer based on +// informations from the HWRenderCallback of the libretro core. +func (video *Video) InitFramebuffer() { + width := int32(video.Geom.MaxWidth) + height := int32(video.Geom.MaxHeight) + + log.Printf("[Video]: Initializing HW render (%v x %v).\n", width, height) + + gl.ActiveTexture(gl.TEXTURE0) + gl.BindTexture(gl.TEXTURE_2D, video.texID) + gl.TexStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, width, height) + + gl.GenFramebuffers(1, &video.fboID) + gl.BindFramebuffer(gl.FRAMEBUFFER, video.fboID) + gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, video.texID, 0) + + hw := state.Global.Core.HWRenderCallback + if hw.Depth { + gl.GenRenderbuffers(1, &video.rboID) + gl.BindRenderbuffer(gl.RENDERBUFFER, video.rboID) + format := gl.DEPTH_COMPONENT16 + if hw.Stencil { + format = gl.DEPTH24_STENCIL8 + } + gl.RenderbufferStorage(gl.RENDERBUFFER, uint32(format), width, height) + gl.BindRenderbuffer(gl.RENDERBUFFER, 0) + + if hw.Stencil { + gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, video.rboID) + } else { + gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, video.rboID) + } + } + + // Default origin is top left + video.orthoMat = mgl32.Ortho2D(-1, 1, -1, 1) + if hw.BottomLeftOrigin { + video.orthoMat = mgl32.Ortho2D(-1, 1, 1, -1) + } + + if st := gl.CheckFramebufferStatus(gl.FRAMEBUFFER); st != gl.FRAMEBUFFER_COMPLETE { + log.Fatalf("[Video] Framebuffer is not complete. Error: %v\n", st) + } + + bindBackbuffer() + + gl.ClearColor(0, 0, 0, 1) + if hw.Depth && hw.Stencil { + gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) + } else if hw.Depth { + gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) + } else { + gl.Clear(gl.COLOR_BUFFER_BIT) + } +} + +func bindBackbuffer() { + gl.BindFramebuffer(gl.FRAMEBUFFER, 0) +} + +func genVertexArrays(n int32, arrays *uint32) { + gl.GenVertexArrays(n, arrays) +} + +func bindVertexArray(array uint32) { + gl.BindVertexArray(array) +} From 73d70cb1f919e20f7f005de37a548add17e55d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sun, 1 Mar 2020 17:37:04 +0700 Subject: [PATCH 31/36] Implement libretro.EnvironmentGetPrefferedHWRenderer --- core/environment.go | 5 ++++- libretro/libretro.go | 41 ++++++++++++++++++++++++----------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/core/environment.go b/core/environment.go index efa3557c..c837869a 100644 --- a/core/environment.go +++ b/core/environment.go @@ -105,7 +105,7 @@ func environment(cmd uint32, data unsafe.Pointer) bool { data, vid.CurrentFramebuffer, vid.ProcAddress) - log.Println("HWContextType:", state.Global.Core.HWRenderCallback.HWContextType) + log.Println("[Env]: HWContextType:", state.Global.Core.HWRenderCallback.HWContextType) return true case libretro.EnvironmentGetCanDupe: libretro.SetBool(data, true) @@ -115,6 +115,9 @@ func environment(cmd uint32, data unsafe.Pointer) bool { return environmentGetSystemDirectory(data) case libretro.EnvironmentGetSaveDirectory: return environmentGetSaveDirectory(data) + case libretro.EnvironmentGetPrefferedHWRenderer: + log.Println("[Env]: EnvironmentGetPrefferedHWRenderer: 1") + libretro.SetUnsigned(data, libretro.HWContextOpenGL) case libretro.EnvironmentShutdown: vid.Window.SetShouldClose(true) case libretro.EnvironmentGetVariable: diff --git a/libretro/libretro.go b/libretro/libretro.go index f3843051..da25dd8f 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -231,23 +231,24 @@ const ( // Environment callback API. See libretro.h for details const ( - EnvironmentSetRotation = uint32(C.RETRO_ENVIRONMENT_SET_ROTATION) - EnvironmentGetUsername = uint32(C.RETRO_ENVIRONMENT_GET_USERNAME) - EnvironmentGetLogInterface = uint32(C.RETRO_ENVIRONMENT_GET_LOG_INTERFACE) - EnvironmentGetCanDupe = uint32(C.RETRO_ENVIRONMENT_GET_CAN_DUPE) - EnvironmentSetPixelFormat = uint32(C.RETRO_ENVIRONMENT_SET_PIXEL_FORMAT) - EnvironmentGetSystemDirectory = uint32(C.RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY) - EnvironmentGetSaveDirectory = uint32(C.RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY) - EnvironmentShutdown = uint32(C.RETRO_ENVIRONMENT_SHUTDOWN) - EnvironmentGetVariable = uint32(C.RETRO_ENVIRONMENT_GET_VARIABLE) - EnvironmentSetVariables = uint32(C.RETRO_ENVIRONMENT_SET_VARIABLES) - EnvironmentGetVariableUpdate = uint32(C.RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE) - EnvironmentGetPerfInterface = uint32(C.RETRO_ENVIRONMENT_GET_PERF_INTERFACE) - EnvironmentSetFrameTimeCallback = uint32(C.RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK) - EnvironmentSetAudioCallback = uint32(C.RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK) - EnvironmentSetHWRenderer = uint32(C.RETRO_ENVIRONMENT_SET_HW_RENDER) - EnvironmentSetGeometry = uint32(C.RETRO_ENVIRONMENT_SET_GEOMETRY) - EnvironmentSetSystemAVInfo = uint32(C.RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO) + EnvironmentSetRotation = uint32(C.RETRO_ENVIRONMENT_SET_ROTATION) + EnvironmentGetUsername = uint32(C.RETRO_ENVIRONMENT_GET_USERNAME) + EnvironmentGetLogInterface = uint32(C.RETRO_ENVIRONMENT_GET_LOG_INTERFACE) + EnvironmentGetCanDupe = uint32(C.RETRO_ENVIRONMENT_GET_CAN_DUPE) + EnvironmentSetPixelFormat = uint32(C.RETRO_ENVIRONMENT_SET_PIXEL_FORMAT) + EnvironmentGetSystemDirectory = uint32(C.RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY) + EnvironmentGetSaveDirectory = uint32(C.RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY) + EnvironmentShutdown = uint32(C.RETRO_ENVIRONMENT_SHUTDOWN) + EnvironmentGetVariable = uint32(C.RETRO_ENVIRONMENT_GET_VARIABLE) + EnvironmentSetVariables = uint32(C.RETRO_ENVIRONMENT_SET_VARIABLES) + EnvironmentGetVariableUpdate = uint32(C.RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE) + EnvironmentGetPerfInterface = uint32(C.RETRO_ENVIRONMENT_GET_PERF_INTERFACE) + EnvironmentSetFrameTimeCallback = uint32(C.RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK) + EnvironmentSetAudioCallback = uint32(C.RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK) + EnvironmentSetHWRenderer = uint32(C.RETRO_ENVIRONMENT_SET_HW_RENDER) + EnvironmentSetGeometry = uint32(C.RETRO_ENVIRONMENT_SET_GEOMETRY) + EnvironmentSetSystemAVInfo = uint32(C.RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO) + EnvironmentGetPrefferedHWRenderer = uint32(C.RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER) ) // Debug levels @@ -684,6 +685,12 @@ func SetString(data unsafe.Pointer, val string) { *s = C.CString(val) } +// SetUnsigned is an environment callback helper to set an unsigned integer +func SetUnsigned(data unsafe.Pointer, val uint32) { + s := (*C.uint)(data) + *s = C.uint(val) +} + // SetFrameTimeCallback is an environment callback helper to set the FrameTimeCallback func (core *Core) SetFrameTimeCallback(data unsafe.Pointer) { c := *(*C.struct_retro_frame_time_callback)(data) From 1e0c4a09661611e2775673f6caae80718c0187f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Mon, 27 Jul 2020 00:10:20 +0700 Subject: [PATCH 32/36] Uncomment gl.Enable(gl.TEXTURE_2D) --- video/video.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/video/video.go b/video/video.go index 22665020..49d000e7 100644 --- a/video/video.go +++ b/video/video.go @@ -355,9 +355,7 @@ func (video *Video) Render() { gl.Disable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.BlendEquation(gl.FUNC_ADD) - - // The next line might be necessary, but doesn't work in core contexts - // gl.Enable(gl.TEXTURE_2D) + gl.Enable(gl.TEXTURE_2D) video.ResizeViewport() From da0092ef53505020c23680535887c29c07539c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Tue, 5 Jan 2021 22:38:01 +0700 Subject: [PATCH 33/36] Fixes --- core/environment.go | 2 +- go.mod | 2 +- libretro/libretro.go | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/environment.go b/core/environment.go index 3daebeab..d253e5b6 100644 --- a/core/environment.go +++ b/core/environment.go @@ -160,7 +160,7 @@ func environment(cmd uint32, data unsafe.Pointer) bool { return environmentGetSaveDirectory(data) case libretro.EnvironmentGetPrefferedHWRenderer: log.Println("[Env]: EnvironmentGetPrefferedHWRenderer: 1") - libretro.SetUint(data, libretro.HWContextOpenGL) + libretro.SetUint(data, uint(libretro.HWContextOpenGL)) case libretro.EnvironmentShutdown: vid.Window.SetShouldClose(true) case libretro.EnvironmentGetCoreOptionsVersion: diff --git a/go.mod b/go.mod index c6b038c9..4bc96676 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/fatih/structs v1.1.0 github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20201108214237-06ea97f0c265 - github.com/go-gl/mathgl v0.0.0-20190713194549-592312d8590a // indirect + github.com/go-gl/mathgl v0.0.0-20190713194549-592312d8590a github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/lucasb-eyer/go-colorful v1.0.2 github.com/pelletier/go-toml v1.6.0 diff --git a/libretro/libretro.go b/libretro/libretro.go index 8825a3af..faf963cb 100644 --- a/libretro/libretro.go +++ b/libretro/libretro.go @@ -326,6 +326,7 @@ const ( EnvironmentSetCoreOptions = uint32(C.RETRO_ENVIRONMENT_SET_CORE_OPTIONS) EnvironmentSetCoreOptionsIntl = uint32(C.RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL) EnvironmentGetLanguage = uint32(C.RETRO_ENVIRONMENT_GET_LANGUAGE) + EnvironmentSetHWRenderer = uint32(C.RETRO_ENVIRONMENT_SET_HW_RENDER) EnvironmentGetPrefferedHWRenderer = uint32(C.RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER) ) From a43843bab155b93e3f6792dbdeacafbb848585ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Sat, 17 Apr 2021 15:40:33 +0700 Subject: [PATCH 34/36] Fix --- go.mod | 2 +- go.sum | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d62b20b2..af77605d 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/fatih/structs v1.1.0 github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20201108214237-06ea97f0c265 - github.com/go-gl/mathgl v0.0.0-20190713194549-592312d8590a + github.com/go-gl/mathgl v1.0.0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/kr/text v0.2.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 diff --git a/go.sum b/go.sum index f8d5d18a..27d95638 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluN github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20201108214237-06ea97f0c265 h1:BcbKYUZo/TKPsiSh7LymK3p+TNAJJW3OfGO/21sBbiA= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20201108214237-06ea97f0c265/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/mathgl v1.0.0 h1:t9DznWJlXxxjeeKLIdovCOVJQk/GzDEL7h/h+Ro2B68= +github.com/go-gl/mathgl v1.0.0/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= @@ -47,6 +49,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067 h1:KYGJGHOQy8oSi1fDlSpcZF0+juKwk/hEMv5SiwHogR0= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= From d74969f50e5a3927b0fbaf856e5999ed6981574a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Fri, 22 Oct 2021 20:09:45 +0700 Subject: [PATCH 35/36] Fix --- video/video_notdarwin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/video_notdarwin.go b/video/video_notdarwin.go index 6e676f18..c5e6415b 100644 --- a/video/video_notdarwin.go +++ b/video/video_notdarwin.go @@ -26,7 +26,7 @@ func (video *Video) InitFramebuffer() { gl.BindFramebuffer(gl.FRAMEBUFFER, video.fboID) gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, video.texID, 0) - hw := state.Global.Core.HWRenderCallback + hw := state.Core.HWRenderCallback if hw.Depth { gl.GenRenderbuffers(1, &video.rboID) gl.BindRenderbuffer(gl.RENDERBUFFER, video.rboID) From cb8649a1297c5471922318fed8dddd0894efcfa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Fri, 22 Oct 2021 20:47:24 +0700 Subject: [PATCH 36/36] Forgot to use program before get uniform --- video/video.go | 1 + 1 file changed, 1 insertion(+) diff --git a/video/video.go b/video/video.go index 0e34dd67..eb8b03f4 100644 --- a/video/video.go +++ b/video/video.go @@ -181,6 +181,7 @@ func (video *Video) Configure(fullscreen bool) { video.UpdateFilter(settings.Current.VideoFilter) + gl.UseProgram(video.program) textureUniform := gl.GetUniformLocation(video.program, gl.Str("Texture\x00")) gl.Uniform1i(textureUniform, 0)