// Package drm is the kernel mode-setting ABI. 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 is larger than the kernel union it mirrors, so WaitVblankIO // carries the union's size and only Type and Sequence are at valid offsets. 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{})) ) const ( redShift = 16 greenShift = 8 blueShift = 0 ) func Pack(r, g, b uint8) uint32 { return uint32(r)<> redShift), uint8(v >> greenShift), uint8(v >> blueShift) } // Offset maps the portrait canvas onto the landscape panel, a quarter turn that // puts logical top on the panel's right edge. func Offset(x, y, stride, panelW int) int { return x*stride + (panelW-1-y)*4 }