image with texture wouldn't redraw - question
marben opened this issue · comments
I am probably missing something, but I can't get an image with attached texture to redraw.
My code follows:
package main
import (
"fmt"
"image"
"image/color"
"github.com/google/gxui"
"github.com/google/gxui/drivers/gl"
"github.com/google/gxui/themes/dark"
)
func appMain(driver gxui.Driver) {
theme := dark.CreateTheme(driver)
window := theme.CreateWindow(640, 480, "test")
rect := image.Rectangle{image.ZP, image.Pt(640, 480)}
rgba := image.NewRGBA(rect)
texture := driver.CreateTexture(rgba, 1)
img := theme.CreateImage()
img.SetTexture(texture)
window.AddChild(img)
rgba.SetRGBA(200, 200, color.RGBA{R: 255})
window.OnMouseDown(func(me gxui.MouseEvent) {
fmt.Println("Mouse Down")
rgba.SetRGBA(210, 200, color.RGBA{G: 255})
img.Draw()
})
window.OnClose(driver.Terminate)
}
func main() {
gl.StartDriver(appMain)
}
The red pixel:
rgba.SetRGBA(200, 200, color.RGBA{R: 255})
is correctly drawn.
However the green pixel in OnMouseDown doesn't appear on the screen after a click.
Hi @marben,
There are two reasons why this doesn't work:
- Control.Draw does not request a UI update - it asks the
Control
to construct and return a new Canvas so it can be drawn into the parent. Container.Redraw is the command to ask aContainer
and it's full parent hierarchy to redraw. When I get some spare time, I'll try to finally get around to documenting theControl
andContainer
interfaces. - Driver.CreateTexture constructs a Texture from the provided image by copying the data to the GPU once. Mutating the image pixels after the copy has been performed will not alter what's seen on the screen. Your example has highlighted the fact that there is a short window of time between the call to
CreateTexture
and the GPU copy, which might cause confusion / bugs. The copy should probably be made immediately.
So currently, the only way to achieve an update is to re-call Driver.CreateTexture
.
I hope this makes sense.
Cheers,
Ben
Ok, I see.
The fact that i could update texture by writing to rgba really confused me.
So I assume i need to call Release()
on the old texture?
Also the image updates without calling Container
's Redraw()
method. Is that right?
Thanks,
Martin
So I assume i need to call Release() on the old texture?
Assume no for now. This is cruft I want to remove, as we shouldn't have ref-counting on any public interface. I'm on vacation at the moment, but I'll make an effort to remove the release logic from the texture and canvas public interfaces when I get back.
Also the image updates without calling Container's Redraw() method. Is that right?
Yes. Calling SetTexture will trigger an internal redraw. Redraw is only public on the Container interface so that a child can propagate the redraw up the parent hierarchy.
Ok,
thank you. That answers all my questions.
Enjoy your vacation.
Currently, if I don't call texture.Release() in case of repeated call to driver.CreateTexture(), memory will leak until GL_OUT_OF_MEMORY is thrown.
https://github.com/tpng/emulator8080/commit/189a57703907f4e2a9f2e71a3e13f7d541841a3d
Removing last.Release() will cause OOM.
Reopening for the Release issue.