Last active
November 26, 2017 06:10
-
-
Save thomas-holmes/0711d7b73e6c893056b66788ba2abdf1 to your computer and use it in GitHub Desktop.
Example of go-sdl SDL_TextureLock bug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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