Skip to content

Fix two race conditions and a type conversion mistake #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions flutter/flutter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ package flutter
import "C"
import (
"encoding/json"
"sync"
"unsafe"
)

// the current FlutterEngine running (associated with his callback)
var flutterEngines []*EngineOpenGL
var flutterEnginesLock sync.RWMutex

// SelectEngine return a EngineOpenGL from an index
func SelectEngine(index int) *EngineOpenGL {
return flutterEngines[index]
flutterEnginesLock.RLock()
engine := flutterEngines[index]
flutterEnginesLock.RUnlock()
return engine
}

// NumberOfEngines return the number of engine registered into this embedder
Expand All @@ -40,6 +45,9 @@ type EngineOpenGL struct {
// Flutter Engine.
Engine C.FlutterEngine

// index of the engine in the global flutterEngines slice
index int

// Necessary callbacks for rendering.
FMakeCurrent func(v unsafe.Pointer) bool
FClearCurrent func(v unsafe.Pointer) bool
Expand All @@ -56,11 +64,24 @@ type EngineOpenGL struct {
IcuDataPath string
}

// Run launches the Flutter Engine in a background thread.
func (flu *EngineOpenGL) Run(window uintptr, vmArgs []string) Result {

// NewEngineOpenGL creates an empty EngineOpenGL
// and assigns it an index for global lookup.
func NewEngineOpenGL() *EngineOpenGL {
flu := &EngineOpenGL{}
flutterEnginesLock.Lock()
flutterEngines = append(flutterEngines, flu)
flu.index = len(flutterEngines) - 1
flutterEnginesLock.Unlock()
return flu
}

// Index returns the index of the engine in the global flutterEngines slice
func (flu *EngineOpenGL) Index() int {
return flu.index
}

// Run launches the Flutter Engine in a background thread.
func (flu *EngineOpenGL) Run(window uintptr, vmArgs []string) Result {
args := C.FlutterProjectArgs{
assets_path: C.CString(flu.AssetsPath),
main_path: C.CString(""),
Expand Down
32 changes: 19 additions & 13 deletions flutter/flutter_proxy_glfw.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
// C proxies

//export proxy_on_platform_message
func proxy_on_platform_message(message *C.FlutterPlatformMessage, userPointer unsafe.Pointer) C.bool {
func proxy_on_platform_message(message *C.FlutterPlatformMessage, window unsafe.Pointer) C.bool {
if message.message != nil {
str := C.GoStringN(C.c_str(message.message), C.int(message.message_size))

Expand All @@ -30,43 +30,49 @@ func proxy_on_platform_message(message *C.FlutterPlatformMessage, userPointer un
Channel: C.GoString(message.channel),
ResponseHandle: message.response_handle,
}
return C.bool(flutterEngines[0].FPlatfromMessage(FlutterPlatformMessage, userPointer))
index := *(*int)(glfw.GoWindow(window).GetUserPointer())
engine := SelectEngine(index)
return C.bool(engine.FPlatfromMessage(FlutterPlatformMessage, window))
}
return C.bool(false)

}

//export proxy_make_current
func proxy_make_current(v unsafe.Pointer) C.bool {
w := glfw.GoWindow(v)
index := *(*C.int)(w.GetUserPointer())
return C.bool(flutterEngines[index].FMakeCurrent(v))
index := *(*int)(w.GetUserPointer())
engine := SelectEngine(index)
return C.bool(engine.FMakeCurrent(v))
}

//export proxy_clear_current
func proxy_clear_current(v unsafe.Pointer) C.bool {
w := glfw.GoWindow(v)
index := *(*C.int)(w.GetUserPointer())
return C.bool(flutterEngines[index].FClearCurrent(v))
index := *(*int)(w.GetUserPointer())
engine := SelectEngine(index)
return C.bool(engine.FClearCurrent(v))
}

//export proxy_present
func proxy_present(v unsafe.Pointer) C.bool {
w := glfw.GoWindow(v)
index := *(*C.int)(w.GetUserPointer())
return C.bool(flutterEngines[index].FPresent(v))
index := *(*int)(w.GetUserPointer())
engine := SelectEngine(index)
return C.bool(engine.FPresent(v))
}

//export proxy_fbo_callback
func proxy_fbo_callback(v unsafe.Pointer) C.uint32_t {
w := glfw.GoWindow(v)
index := *(*C.int)(w.GetUserPointer())
return C.uint32_t(flutterEngines[index].FFboCallback(v))
index := *(*int)(w.GetUserPointer())
engine := SelectEngine(index)
return C.uint32_t(engine.FFboCallback(v))
}

//export proxy_make_resource_current
func proxy_make_resource_current(v unsafe.Pointer) C.bool {
w := glfw.GoWindow(v)
index := *(*C.int)(w.GetUserPointer())
return C.bool(flutterEngines[index].FMakeResourceCurrent(v))
index := *(*int)(w.GetUserPointer())
engine := SelectEngine(index)
return C.bool(engine.FMakeResourceCurrent(v))
}
59 changes: 29 additions & 30 deletions gutter.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,33 +184,32 @@ func glfwCharCallback(w *glfw.Window, char rune) {
// Flutter Engine
func runFlutter(window *glfw.Window, c config) *flutter.EngineOpenGL {

flutterOGL := flutter.EngineOpenGL{
// Engine arguments
AssetsPath: c.AssetPath,
IcuDataPath: c.ICUDataPath,
// Render callbacks
FMakeCurrent: func(v unsafe.Pointer) bool {
w := glfw.GoWindow(v)
w.MakeContextCurrent()
return true
},
FClearCurrent: func(v unsafe.Pointer) bool {
glfw.DetachCurrentContext()
return true
},
FPresent: func(v unsafe.Pointer) bool {
w := glfw.GoWindow(v)
w.SwapBuffers()
return true
},
FFboCallback: func(v unsafe.Pointer) int32 {
return 0
},
FMakeResourceCurrent: func(v unsafe.Pointer) bool {
return false
},
PixelRatio: c.PixelRatio,
flutterOGL := flutter.NewEngineOpenGL()
// Engine arguments
flutterOGL.AssetsPath = c.AssetPath
flutterOGL.IcuDataPath = c.ICUDataPath
// Render callbacks
flutterOGL.FMakeCurrent = func(v unsafe.Pointer) bool {
w := glfw.GoWindow(v)
w.MakeContextCurrent()
return true
}
flutterOGL.FClearCurrent = func(v unsafe.Pointer) bool {
glfw.DetachCurrentContext()
return true
}
flutterOGL.FPresent = func(v unsafe.Pointer) bool {
w := glfw.GoWindow(v)
w.SwapBuffers()
return true
}
flutterOGL.FFboCallback = func(v unsafe.Pointer) int32 {
return 0
}
flutterOGL.FMakeResourceCurrent = func(v unsafe.Pointer) bool {
return false
}
flutterOGL.PixelRatio = c.PixelRatio

// PlatformMessage
flutterOGL.FPlatfromMessage = func(platMessage *flutter.PlatformMessage, window unsafe.Pointer) bool {
Expand All @@ -221,7 +220,7 @@ func runFlutter(window *glfw.Window, c config) *flutter.EngineOpenGL {
// Dispatch the message from the Flutter Engine, to all of the PluginReceivers
// having the same flutter.PlatformMessage.Channel name
for _, receivers := range c.PlatformMessageReceivers[platMessage.Channel] {
hasDispatched = receivers(platMessage, &flutterOGL, windows) || hasDispatched
hasDispatched = receivers(platMessage, flutterOGL, windows) || hasDispatched
}

return hasDispatched
Expand All @@ -232,8 +231,8 @@ func runFlutter(window *glfw.Window, c config) *flutter.EngineOpenGL {
updateEditingState(window)
}

NbEngine := flutter.NumberOfEngines()
window.SetUserPointer(unsafe.Pointer(&NbEngine))
flutterOGLIndex := flutterOGL.Index()
window.SetUserPointer(unsafe.Pointer(&flutterOGLIndex))
result := flutterOGL.Run(window.GLFWWindow(), c.VMArguments)

if result != flutter.KSuccess {
Expand All @@ -255,7 +254,7 @@ func runFlutter(window *glfw.Window, c config) *flutter.EngineOpenGL {
window.SetFramebufferSizeCallback(glfwWindowSizeCallback)
window.SetMouseButtonCallback(glfwMouseButtonCallback)
window.SetCharCallback(glfwCharCallback)
return &flutterOGL
return flutterOGL
}

// Update the TextInput with the current state
Expand Down