Compare commits

...
Author SHA1 Message Date
Jean-André Santoni bd99584fe9 Add sdf rounded rect shader 2019-10-11 23:16:35 +07:00
Jean-André Santoni 933c86b852 Update dependency for GetProcAddress 2019-10-08 10:55:36 +07:00
Jean-André Santoni 681dfbc6ab Merge branch 'master' into kivutar/gl 2019-10-08 09:51:48 +07:00
Jean-André Santoni f241ef4995 List hardware contexts in the libretro binding 2019-03-12 23:58:12 +07:00
Jean-André Santoni 6e4b4b634e Remove useless code 2019-03-12 21:32:28 +07:00
Jean-André Santoni 87175ca350 Call vid.InitFramebuffer and Core.HWRenderCallback.ContextReset during LoadGame 2019-03-12 19:58:20 +07:00
Jean-André Santoni 7eef38cf2e Comment 2019-03-12 19:00:31 +07:00
Jean-André Santoni dc56ebfff9 Merge branch 'master' into kivutar/gl 2019-03-12 18:52:09 +07:00
Jean-André Santoni d3fd407e77 Move InitFramebuffer and call HWRenderCallback.ContextReset 2019-02-22 16:32:59 +07:00
Jean-André Santoni a7cf8d1f99 Implement more of InitFramebuffer 2019-02-22 16:27:24 +07:00
Jean-André Santoni a7da8f7cb9 Fix display of non gl cores 2019-02-22 16:18:06 +07:00
Jean-André Santoni 967b0da04f Merge remote-tracking branch 'origin/master' into kivutar/gl 2019-02-22 15:55:55 +07:00
Jean-André Santoni c6c0c9c819 Try to implement ProcAddress 2018-12-30 13:03:25 +07:00
Jean-André Santoni d41ab5d9d7 TODO 2018-12-30 12:38:54 +07:00
Jean-André Santoni 7e794694f5 Start implementing InitFramebuffer 2018-12-30 12:33:24 +07:00
Jean-André Santoni d861e3d47d Improve the libretro binding to support GL cores 2018-12-30 11:46:35 +07:00
14 changed files with 236 additions and 4 deletions

No files matched your search

+1 -1
View File
@@ -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))
+6
View File
@@ -175,6 +175,12 @@ 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 {
state.Global.Core.HWRenderCallback.ContextReset()
}
return nil
}
+5
View File
@@ -98,6 +98,11 @@ func environment(cmd uint32, data unsafe.Pointer) bool {
state.Global.Core.SetFrameTimeCallback(data)
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
return true
case libretro.EnvironmentGetCanDupe:
libretro.SetBool(data, true)
case libretro.EnvironmentSetPixelFormat:
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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=
+8
View File
@@ -22,6 +22,14 @@ 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();
}
void bridge_retro_audio_callback(retro_audio_callback_t f) {
f();
}
+52
View File
@@ -33,6 +33,8 @@ 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);
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);
size_t bridge_retro_get_memory_size(void *f, unsigned id);
@@ -123,6 +125,22 @@ type FrameTimeCallback struct {
Reference int64
}
// HWRenderCallback sets an interface to let a libretro core render with
// hardware acceleration.
type HWRenderCallback struct {
HWContextType uint32
ContextReset func()
GetCurrentFramebuffer func() uintptr
GetProcAddress func(string) uintptr
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()
@@ -224,6 +242,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)
EnvironmentSetGeometry = uint32(C.RETRO_ENVIRONMENT_SET_GEOMETRY)
EnvironmentSetSystemAVInfo = uint32(C.RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO)
)
@@ -246,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)
@@ -633,6 +664,27 @@ func (core *Core) SetFrameTimeCallback(data unsafe.Pointer) {
core.FrameTimeCallback = 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 = uint32(c.context_type)
hwrc.ContextReset = func() {
C.bridge_retro_hw_context_reset(c.context_reset)
}
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 (core *Core) SetAudioCallback(data unsafe.Pointer) {
c := *(*C.struct_retro_audio_callback)(data)
+1
View File
@@ -42,6 +42,7 @@ type Core struct {
AudioCallback *AudioCallback
FrameTimeCallback *FrameTimeCallback
HWRenderCallback *HWRenderCallback
}
// DlSym loads a symbol from a dynamic library
+1
View File
@@ -33,6 +33,7 @@ type Core struct {
AudioCallback *AudioCallback
FrameTimeCallback *FrameTimeCallback
HWRenderCallback *HWRenderCallback
}
// DlSym loads a symbol from a dynamic library
+3
View File
@@ -293,6 +293,9 @@ func (tabs sceneTags) drawHintBar() {
w, h := vid.Window.GetFramebufferSize()
vid.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, video.Color{R: 0.75, G: 0.75, B: 0.75, A: 1})
vid.DrawTest(120, 120, 280, 200, 0.05, video.Color{R: 0, G: 0, B: 0, A: 0.2})
vid.DrawRect(100, 100, 320, 240, 0.01, video.Color{R: 1, G: 0, B: 1, A: 1})
_, _, leftRight, a, _, _, _, _, _, guide := hintIcons()
var stack float32
+27
View File
@@ -120,6 +120,33 @@ func (video *Video) DrawRect(x, y, w, h, r float32, c Color) {
gl.Disable(gl.BLEND)
}
func (video *Video) DrawTest(x, y, w, h, r float32, c Color) {
fbw, fbh := video.Window.GetFramebufferSize()
va := []float32{
-1, -1, +0, +1,
-1, +1, +0, +0,
+1, -1, +1, +1,
+1, +1, +1, +0,
}
gl.UseProgram(video.testProgram)
gl.Uniform4f(gl.GetUniformLocation(video.testProgram, gl.Str("box\x00")), x, y, x+w, y+h)
gl.Uniform4f(gl.GetUniformLocation(video.testProgram, gl.Str("color\x00")), c.R, c.G, c.B, c.A)
gl.Uniform1f(gl.GetUniformLocation(video.testProgram, gl.Str("radius\x00")), r)
gl.Uniform2f(gl.GetUniformLocation(video.testProgram, gl.Str("resolution\x00")), float32(fbw), float32(fbh))
gl.Enable(gl.BLEND)
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
gl.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)
gl.UseProgram(0)
gl.Disable(gl.BLEND)
}
// DrawCircle draws a circle
func (video *Video) DrawCircle(x, y, r float32, c Color) {
+40
View File
@@ -0,0 +1,40 @@
package video
var testFragmentShader = `
#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#define COMPAT_FRAGCOLOR FragColor
out vec4 COMPAT_FRAGCOLOR;
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#define COMPAT_FRAGCOLOR gl_FragColor
#endif
uniform vec4 box;
uniform vec4 color;
uniform float radius;
uniform vec2 resolution;
COMPAT_VARYING vec2 fragTexCoord;
float rec(vec2 uv, vec2 tl, vec2 br)
{
vec2 d = max(tl-uv, uv-br);
return length(max(vec2(0.0), d)) + min(0.0, max(d.x, d.y));
}
void main() {
vec2 st = gl_FragCoord.xy/resolution;
st -= 0.5;
st *= vec2(resolution.x/resolution.y, -1.0);
st += vec2(0.5*resolution.x/resolution.y, 0.5);
float d = rec(st, box.xy/resolution.y, box.zw/resolution.y);
float m = 1.0 - d/radius;
COMPAT_FRAGCOLOR = vec4(color.rgb, m*color.a);
}
` + "\x00"
+26
View File
@@ -0,0 +1,26 @@
package video
var testVertexShader = `
#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#define COMPAT_FRAGCOLOR FragColor
out vec4 COMPAT_FRAGCOLOR;
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#define COMPAT_FRAGCOLOR gl_FragColor
#endif
COMPAT_ATTRIBUTE vec2 vert;
COMPAT_ATTRIBUTE vec2 vertTexCoord;
COMPAT_VARYING vec2 fragTexCoord;
void main() {
fragTexCoord = vertTexCoord;
gl_Position = vec4(vert, 0.0, 1.0);
}
` + "\x00"
+63
View File
@@ -45,6 +45,7 @@ type Video struct {
borderProgram uint32 // program to draw rectangles borders
circleProgram uint32 // program to draw textured circles
demulProgram uint32 // program to draw premultiplied alpha images
testProgram uint32
vao uint32
vbo uint32
texID uint32
@@ -52,6 +53,8 @@ type Video struct {
pixFmt uint32
pixType uint32
bpp int32
fboID uint32
rboID uint32
}
// Init instanciates the video package
@@ -125,6 +128,45 @@ 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)
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
func (video *Video) Configure(fullscreen bool) {
var width, height int
@@ -210,6 +252,11 @@ func (video *Video) Configure(fullscreen bool) {
panic(err)
}
video.testProgram, err = newProgram(GLSLVersion, testVertexShader, testFragmentShader)
if err != nil {
panic(err)
}
video.UpdateFilter(settings.Current.VideoFilter)
textureUniform := gl.GetUniformLocation(video.program, gl.Str("Texture\x00"))
@@ -250,6 +297,11 @@ func (video *Video) Configure(fullscreen bool) {
gl.BindTexture(gl.TEXTURE_2D, video.texID)
video.UpdateFilter(settings.Current.VideoFilter)
if state.Global.CoreRunning {
video.InitFramebuffer(video.Geom.BaseWidth, video.Geom.BaseHeight)
state.Global.Core.HWRenderCallback.ContextReset()
}
}
// UpdateFilter configures the game texture filter and shader. We currently
@@ -387,6 +439,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)
@@ -403,6 +456,16 @@ func (video *Video) Refresh(data unsafe.Pointer, width int32, height int32, pitc
gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, video.pixType, video.pixFmt, data)
}
// CurrentFramebuffer returns the current FBO ID
func (video *Video) CurrentFramebuffer() uintptr {
return uintptr(video.fboID)
}
// ProcAddress returns the address of the proc from GLFW
func (video *Video) ProcAddress(procName string) uintptr {
return uintptr(glfw.GetProcAddress(procName))
}
var vertices = []float32{
// X, Y, U, V
-1.0, -1.0, 0.0, 1.0, // left-bottom