Flickering when using glfwcanvas
Hi there, thanks for your awesome library! It is refreshingly easy to use!
I'm trying to use it to render a sequence of images in a glfwcanvas, but when I update the image with a new one, it keeps switching between the new and the old image. Here's a snippet of my code:
win, cv, err := glfwcanvas.CreateWindow(defaultWidth, defaultHeight, windowTitle)
if err != nil {
panic(err)
}
var lastRefresh int64
win.MainLoop(func() {
// This call returns a new image and the last timestamp it was updated
img, lastUpdate := client.Screen()
imgWidth := img.Bounds().Max.X
imgHeight := img.Bounds().Max.Y
// If the image is empty, terminate loop
if imgWidth == 0 || imgHeight == 0 {
return
}
// If there were no changes, terminate loop
if lastRefresh == lastUpdate {
return
}
// Process screen updates
cv.PutImageData(img.(*image.RGBA), 0, 0)
lastRefresh = lastUpdate
})
I tried to use cv.DrawImage() but then it does not show anything. What am I doing wrong?
Hi! Thanks for the nice comments!
I don't see anything wrong with the code, and cv.DrawImage should also work. I tried writing a test function for client.Screen to test it out, but it seems to work fine for me. Can you try this and see if that works? If not, it may be an OpenGL or driver issue maybe...
package main
import (
"image"
"image/color"
"math/rand"
"time"
"github.com/tfriedel6/canvas/glfwcanvas"
)
var (
first = true
bla = time.Now()
limg *image.RGBA
)
func clientScreen() (image.Image, int64) {
if !first && rand.Float64() < 0.99 {
return limg, bla.UnixNano()
}
first = false
rgba := image.NewRGBA(image.Rect(0, 0, 800, 800))
for y := 0; y < 800; y++ {
for x := 0; x < 800; x++ {
rgba.Set(x, y, color.RGBA{
R: byte(rand.Intn(256)),
G: byte(rand.Intn(256)),
B: byte(rand.Intn(256)),
A: 255,
})
}
}
bla = time.Now()
limg = rgba
return rgba, bla.UnixNano()
}
func main() {
win, cv, err := glfwcanvas.CreateWindow(800, 800, "hello")
if err != nil {
panic(err)
}
var lastRefresh int64
win.MainLoop(func() {
// This call returns a new image and the last timestamp it was updated
img, lastUpdate := clientScreen()
imgWidth := img.Bounds().Max.X
imgHeight := img.Bounds().Max.Y
// If the image is empty, terminate loop
if imgWidth == 0 || imgHeight == 0 {
return
}
// If there were no changes, terminate loop
if lastRefresh == lastUpdate {
return
}
// Process screen updates
// cv.PutImageData(img.(*image.RGBA), 0, 0)
cv.DrawImage(img, 0, 0)
lastRefresh = lastUpdate
})
}
This is definitely an issue with OpenGL, as it works flawless with SDL. I tried my code with SDL and it worked. I also tried your code and it still flicks (and scales down the image, weird), but when I try it with SDL it also works perfectly.
I think it is worth to note that OpenGL is working in my machine. I'm actually trying to port my code from using Pixel to your library, and with Pixel it works ok.
My system is macOS Mojave, I don't have an easy way to test this in other systems, but I'm willing to help in anyway I can to make this work, as I rather not have to install extra dependencies (SDL2) for my code to work.
This will be difficult for me to test, as I don't have a Mac available to test on. I do have a VM running macOS, but it is an old version and I can't even install the latest Xcode on it. I tried running the GLFW example on that, but it just crashes immediately (SDL works though).
One thing worth trying might be to get it running on the latest versions GLFW. In case you want to do this you could just copy the glfwcanvas package into a package of your own and use that, then go get the latest github.com/go-gl/glfw version. If that helps, let me know and I will update the dependency here. If not, you can try the 3.3-beta branch (run go get github.com/go-gl/[email protected]) and see if you can get it to run with GLFW 3.3.