Skip to content

Instantly share code, notes, and snippets.

@thomas-holmes
Last active November 26, 2017 06:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomas-holmes/0711d7b73e6c893056b66788ba2abdf1 to your computer and use it in GitHub Desktop.
Save thomas-holmes/0711d7b73e6c893056b66788ba2abdf1 to your computer and use it in GitHub Desktop.
Example of go-sdl SDL_TextureLock bug
package main
import (
"github.com/veandco/go-sdl2/sdl"
)
func main() {
if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil {
panic(err)
}
defer sdl.Quit()
window, err := sdl.CreateWindow("test", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
800, 600, sdl.WINDOW_SHOWN)
if err != nil {
panic(err)
}
defer window.Destroy()
renderer, err := sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
if err != nil {
panic(err)
}
renderer.SetDrawColor(255, 0, 0, 0)
renderer.Clear()
tex, err := renderer.CreateTexture(sdl.PIXELFORMAT_ABGR8888, sdl.TEXTUREACCESS_STREAMING, 400, 400)
rect := sdl.Rect{100, 100, 200, 200}
// We'll lock the texture to draw a centered yellow square.
bytes, pitch, err := tex.Lock(&rect)
_ = pitch
if err != nil {
panic(err)
}
tex.SetBlendMode(sdl.BLENDMODE_NONE)
// We set every pixel in the buffer handed to us to yellow.
// Unfortunately the buffer is way too small! We get a buffer of
// 200 * 200 * 4, or 160,000 elements but a pitch of 3200. This
// leaves us without enough entries to properly fill in our locked rectangle
// We'll draw our texture right in the middle. Unfortunately we only get the
// top half of the yellow square we desire. Half of the pixels we are writing
// are outside of the locked range and are disregarded.
// With this fixed Lock function this code will segfault
for i := 0; i < len(bytes); i += 4 {
bytes[i] = 255
bytes[i+1] = 255
bytes[i+2] = 0
bytes[i+3] = 255
}
tex.Unlock()
targetRect := sdl.Rect{
X: 200,
Y: 100,
W: 400,
H: 400,
}
renderer.Copy(tex, nil, &targetRect)
renderer.Present()
sdl.Delay(5000)
}
package main
import (
"log"
"github.com/veandco/go-sdl2/sdl"
)
func main() {
if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil {
panic(err)
}
defer sdl.Quit()
window, err := sdl.CreateWindow("test", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
800, 600, sdl.WINDOW_SHOWN)
if err != nil {
panic(err)
}
defer window.Destroy()
renderer, err := sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
if err != nil {
panic(err)
}
renderer.SetDrawColor(255, 0, 0, 0)
renderer.Clear()
tex, err := renderer.CreateTexture(sdl.PIXELFORMAT_ABGR8888, sdl.TEXTUREACCESS_STREAMING, 400, 400)
rect := sdl.Rect{100, 100, 200, 200}
// We'll lock the texture to draw a centered yellow square.
bytes, pitch, err := tex.Lock(&rect)
_ = pitch
if err != nil {
panic(err)
}
tex.SetBlendMode(sdl.BLENDMODE_NONE)
// We set every pixel in the buffer handed to us to yellow.
// Unfortunately the buffer is way too small! We get a buffer of
// 200 * 200 * 4, or 160,000 elements but a pitch of 3200. This
// leaves us without enough entries to properly fill in our locked rectangle
// We'll draw our texture right in the middle. Unfortunately we only get the
// top half of the yellow square we desire. Half of the pixels we are writing
// are outside of the locked range and are disregarded.
// Should be row 100, col [100, 400) (only [100,300) are editable)
// rows 101-198, col [ 0, 400) (only [100,300) are editable)
// row 199, col [ 0, 300) (only [100,300) are editable)
// Total Pixels: (300) + (198 * 400) + (300)
// Array Elements: Total Pixels * 4
log.Println("How long is the array", len(bytes))
/*
for i := 0; i < len(bytes); i += 4 {
bytes[i] = 255
bytes[i+1] = 255
bytes[i+2] = 0
bytes[i+3] = 255
}
*/
// This is gross a bit gross but it gets the point across
subPixelComponentsWritten := 0
xOffset := 0
yOffset := 0
for y := 100; y < 300; y++ {
for x := 100; x < 300; x++ {
pixelPosition := ((x - 100) * 4)
bytes[yOffset+xOffset+pixelPosition+0] = 255
bytes[yOffset+xOffset+pixelPosition+1] = 0
bytes[yOffset+xOffset+pixelPosition+2] = 255
bytes[yOffset+xOffset+pixelPosition+3] = 255
subPixelComponentsWritten += 4
}
xOffset = 100 * 4
if y == 100 {
yOffset += pitch - (100 * 4)
} else {
yOffset += pitch
}
}
// Bytes array is of size 319200 but only 160000 sub pixel components were written
log.Printf("Bytes array is of size %v but only %v sub pixel components were written", len(bytes), subPixelComponentsWritten)
tex.Unlock()
targetRect := sdl.Rect{
X: 200,
Y: 100,
W: 400,
H: 400,
}
renderer.Copy(tex, nil, &targetRect)
renderer.Present()
sdl.Delay(5000)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment