146 lines
4.1 KiB
Go
146 lines
4.1 KiB
Go
// Package drm is the kernel mode-setting ABI, shared by the panel this draws on
|
|
// and the grabber that reads it back out. These structs are a layout contract,
|
|
// so a field added or reordered in one copy and not the other would silently
|
|
// misread the kernel: there is deliberately only one copy.
|
|
package drm
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
const ioctlBase = 0x64
|
|
|
|
func IO(nr uintptr) uintptr { return ioctlBase<<8 | nr }
|
|
func IOWR(nr, size uintptr) uintptr { return 3<<30 | size<<16 | ioctlBase<<8 | nr }
|
|
|
|
func Ioctl(fd int, req uintptr, arg unsafe.Pointer) error {
|
|
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), req, uintptr(arg)); errno != 0 {
|
|
return errno
|
|
}
|
|
return nil
|
|
}
|
|
|
|
const (
|
|
Connected = 1
|
|
TypePreferred = 1 << 3
|
|
PageFlipEvent = 0x01
|
|
EventFlipComplete = 0x02
|
|
|
|
VblankRelative = 0x1
|
|
VblankHighCrtcMask = 0x3e
|
|
VblankHighCrtcShift = 1
|
|
)
|
|
|
|
type ModeInfo struct {
|
|
Clock uint32
|
|
Hdisplay, HsyncStart, HsyncEnd, Htotal, Hskew uint16
|
|
Vdisplay, VsyncStart, VsyncEnd, Vtotal, Vscan uint16
|
|
Vrefresh, Flags, Type uint32
|
|
Name [32]byte
|
|
}
|
|
|
|
type ModeCardRes struct {
|
|
FBIDPtr, CrtcIDPtr, ConnIDPtr, EncIDPtr uint64
|
|
CountFBs, CountCRTCs, CountConns, CountEncs uint32
|
|
MinWidth, MaxWidth, MinHeight, MaxHeight uint32
|
|
}
|
|
|
|
type ModeGetConnector struct {
|
|
EncodersPtr, ModesPtr, PropsPtr, PropValuesPtr uint64
|
|
CountModes, CountProps, CountEncoders uint32
|
|
EncoderID, ConnectorID, ConnectorType uint32
|
|
ConnectorTypeID, Connection uint32
|
|
MmWidth, MmHeight, Subpixel, Pad uint32
|
|
}
|
|
|
|
type ModeGetEncoder struct {
|
|
EncoderID, EncoderType uint32
|
|
CrtcID uint32
|
|
PossibleCRTCs, PossibleClones uint32
|
|
}
|
|
|
|
type ModeCrtc struct {
|
|
SetConnectorsPtr uint64
|
|
CountConnectors uint32
|
|
CrtcID uint32
|
|
FBID uint32
|
|
X, Y uint32
|
|
GammaSize uint32
|
|
ModeValid uint32
|
|
Mode ModeInfo
|
|
}
|
|
|
|
type ModeFBCmd struct {
|
|
FBID, Width, Height, Pitch, Bpp, Depth uint32
|
|
Handle uint32
|
|
}
|
|
|
|
type ModeCreateDumb struct {
|
|
Height, Width, Bpp, Flags uint32
|
|
Handle, Pitch uint32
|
|
Size uint64
|
|
}
|
|
|
|
type ModeMapDumb struct {
|
|
Handle, Pad uint32
|
|
Offset uint64
|
|
}
|
|
|
|
type ModeCrtcPageFlip struct {
|
|
CrtcID, FBID, Flags, Reserved uint32
|
|
UserData uint64
|
|
}
|
|
|
|
// WaitVblank has only Type and Sequence ever set, and those sit at the same
|
|
// offsets in both arms of the kernel's union. The request below carries the
|
|
// union's own size rather than this struct's, which is larger.
|
|
type WaitVblank struct {
|
|
Type uint32
|
|
Sequence uint32
|
|
Signal uint64
|
|
TvSec int64
|
|
TvUsec int64
|
|
}
|
|
|
|
const waitVblankUnionSize = 24
|
|
|
|
var (
|
|
SetMaster = IO(0x1e)
|
|
DropMaster = IO(0x1f)
|
|
WaitVblankIO = IOWR(0x3a, waitVblankUnionSize)
|
|
GetResources = IOWR(0xa0, unsafe.Sizeof(ModeCardRes{}))
|
|
GetCrtc = IOWR(0xa1, unsafe.Sizeof(ModeCrtc{}))
|
|
SetCrtc = IOWR(0xa2, unsafe.Sizeof(ModeCrtc{}))
|
|
GetEncoder = IOWR(0xa6, unsafe.Sizeof(ModeGetEncoder{}))
|
|
GetConnector = IOWR(0xa7, unsafe.Sizeof(ModeGetConnector{}))
|
|
GetFB = IOWR(0xad, unsafe.Sizeof(ModeFBCmd{}))
|
|
AddFB = IOWR(0xae, unsafe.Sizeof(ModeFBCmd{}))
|
|
PageFlip = IOWR(0xb0, unsafe.Sizeof(ModeCrtcPageFlip{}))
|
|
CreateDumb = IOWR(0xb2, unsafe.Sizeof(ModeCreateDumb{}))
|
|
MapDumb = IOWR(0xb3, unsafe.Sizeof(ModeMapDumb{}))
|
|
)
|
|
|
|
// What ADDFB means by 32 bits per pixel and 24 bits of colour.
|
|
const (
|
|
redShift = 16
|
|
greenShift = 8
|
|
blueShift = 0
|
|
)
|
|
|
|
func Pack(r, g, b uint8) uint32 {
|
|
return uint32(r)<<redShift | uint32(g)<<greenShift | uint32(b)<<blueShift
|
|
}
|
|
|
|
func Unpack(v uint32) (r, g, b uint8) {
|
|
return uint8(v >> redShift), uint8(v >> greenShift), uint8(v >> blueShift)
|
|
}
|
|
|
|
// Offset turns the quarter turn between the portrait canvas and the landscape
|
|
// panel, putting logical top on the panel's right edge. Drawing and reading
|
|
// back have to agree on this exactly.
|
|
func Offset(x, y, stride, panelW int) int {
|
|
return x*stride + (panelW-1-y)*4
|
|
}
|