I wrote the following test just to see if I can cause screen tearing to happen on my monitor. It simply draws a red square which moves across the screen. Each iteration of the loop moves the square 1 pixel to the right, then resets to column 0 when it reaches the end.
Code: Select all
vsync_test :: proc "c" (st: ^efi.SYSTEM_TABLE) {
graphics_output_protocol_guid := efi.GRAPHICS_OUTPUT_PROTOCOL_GUID
graphics_output_protocol: ^efi.GRAPHICS_OUTPUT_PROTOCOL
st.BootServices.LocateProtocol(&graphics_output_protocol_guid, nil, cast(^rawptr) &graphics_output_protocol)
base_address := cast(^u32) cast(uintptr) graphics_output_protocol.Mode.FrameBufferBase
hres := cast(int) graphics_output_protocol.Mode.Info.HorizontalResolution
print(st.ConOut, "\r\nPress any key to stop\r\n")
st.ConIn.Reset(st.ConIn, false)
key: efi.INPUT_KEY
col := 0
for {
if st.ConIn.ReadKeyStroke(st.ConIn, &key) != .NOT_READY {
break
}
// Clear left column
if col != 0 {
for r in 0 ..< 100 {
pos := hres * r + (col - 1)
pixel := mem.ptr_offset(base_address, pos)
pixel^ = 0x00000000
}
}
// Draw square
for c in col ..< col + 100 {
for r in 0 ..< 100 {
pos := hres * r + c
pixel := mem.ptr_offset(base_address, pos)
pixel^ = 0x00FF0000
}
}
col += 1
if col == hres - 100 {
col = 0
}
}
}
I should also note, I did try removing the ReadKeyStroke() call incase that is a very slow function call and that didn't affect the speed.
When I write to the GOP framebuffer, maybe those writes are just really slow? Maybe this framebuffer memory I'm writing to isn't actually in my system RAM, it's in my graphics adapter's memory which is slow to write to? Or are the memory writes being limited by something else? I very curious on what is exactly going on here.
