private bool PollReadable(int timeoutMs) { LibC.PollFd fd = new LibC.PollFd(); fd.fd = _drmFd; fd.events = LibC.POLLIN | LibC.POLLPRI; LibC.PollFd[] fds = new LibC.PollFd[] { fd }; int rc = LibC.Poll(fds, timeoutMs); return(rc > 0); }
public override void EnterMessageLoop(bool runInBackground) { bool running = true; SizeChanged?.Invoke(this, _width, _height); Activated?.Invoke(this); IntPtr bo = Gbm.SurfaceLockFrontBuffer(_gbmSurface); uint fb = GetFbForBo(bo); IntPtr connectors = System.Runtime.InteropServices.Marshal.AllocHGlobal(sizeof(uint)); System.Runtime.InteropServices.Marshal.WriteInt32(connectors, (int)_drmConnectorId); int rc = Drm.ModeSetCrtc(_drmFd, _drmEncoderCrtcId, fb, 0, 0, connectors, 1, ref _drmMode); System.Runtime.InteropServices.Marshal.FreeHGlobal(connectors); if (rc != 0) { throw new Exception("Failed to create DRM Mode"); } while (running) { LibEvdev.HandleEvents(); Render?.Invoke(this); IntPtr prevBo = bo; bo = Gbm.SurfaceLockFrontBuffer(_gbmSurface); fb = GetFbForBo(bo); Drm.ModePageFlip(_drmFd, _drmEncoderCrtcId, fb, Drm.MODE_PAGE_FLIP_EVENT, IntPtr.Zero); LibC.PollFd fd = new LibC.PollFd(); fd.fd = _drmFd; fd.events = LibC.POLLIN | LibC.POLLPRI; LibC.PollFd[] fds = new LibC.PollFd[] { fd }; LibC.Poll(fds, -1); Drm.EventContext evctx = new Drm.EventContext(); evctx.version = 2; Drm.HandleEvent(_drmFd, ref evctx); if (prevBo != IntPtr.Zero) { Gbm.SurfaceReleaseBuffer(_gbmSurface, prevBo); } } }
public GbmDisplay(string drmDevice) { _close = false; IntPtr udev = LibUdev.New(); _drmFd = LibC.Open(drmDevice, LibC.O_RDWR); if (_drmFd == -1) { IntPtr udevMonitor = LibUdev.MonitorNewFromNetlink(udev, "udev"); LibUdev.MonitorFilterAddMatchSubsystemDevtype(udevMonitor, "drm", null); LibUdev.MonitorEnableReceiving(udevMonitor); int udevMonitorFd = LibUdev.MonitorGetFd(udevMonitor); LibC.PollFd fd = new LibC.PollFd(); fd.fd = udevMonitorFd; fd.events = LibC.POLLIN | LibC.POLLPRI; LibC.PollFd[] fds = { fd }; while (_drmFd == -1) { int rc = LibC.Poll(fds, -1); if (rc > 0) { IntPtr device = LibUdev.MonitorReceiveDevice(udevMonitor); if (device == IntPtr.Zero) { break; } IntPtr deviceAction = LibUdev.DeviceGetAction(device); IntPtr deviceName = LibUdev.DeviceGetDevnode(device); string devAction = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(deviceAction); if (devAction == "add") { _drmFd = LibC.Open(drmDevice, LibC.O_RDWR); } LibUdev.DeviceUnref(device); } } LibUdev.MonitorUnref(udevMonitor); } LibUdev.Unref(udev); IntPtr resourcesPtr = Drm.ModeGetResources(_drmFd); Drm.ModeRes resources = System.Runtime.InteropServices.Marshal.PtrToStructure <Drm.ModeRes>(resourcesPtr); for (int i = 0; i < resources.countConnectors; ++i) { uint connectorId = (uint)System.Runtime.InteropServices.Marshal.ReadInt32(resources.connectors, i * sizeof(uint)); IntPtr connectorPtr = Drm.ModeGetConnector(_drmFd, connectorId); Drm.ModeConnector connector = System.Runtime.InteropServices.Marshal.PtrToStructure <Drm.ModeConnector>(connectorPtr); if (connector.connection == Drm.MODE_CONNECTED) { _drmConnectorId = connector.connectorId; int SizeOfDrmModeModeInfo = System.Runtime.InteropServices.Marshal.SizeOf <Drm.ModeModeInfo>(); int area = 0; for (int j = 0; j < connector.countModes; ++j) { Drm.ModeModeInfo drmMode = System.Runtime.InteropServices.Marshal.PtrToStructure <Drm.ModeModeInfo>(IntPtr.Add(connector.modes, j * SizeOfDrmModeModeInfo)); if ((drmMode.type & Drm.MODE_TYPE_PREFERRED) != 0) { int modeArea = drmMode.hdisplay * drmMode.vdisplay; if (modeArea > area) { _drmMode = drmMode; _width = drmMode.hdisplay; _height = drmMode.vdisplay; area = modeArea; } } } for (int j = 0; j < resources.countEncoders; ++j) { uint encoderId = (uint)System.Runtime.InteropServices.Marshal.ReadInt32(resources.encoders, j * sizeof(uint)); IntPtr encoderPtr = Drm.ModeGetEncoder(_drmFd, encoderId); Drm.ModeEncoder encoder = System.Runtime.InteropServices.Marshal.PtrToStructure <Drm.ModeEncoder>(encoderPtr); for (int k = 0; k < resources.countCrtcs; ++k) { uint crtcMask = (uint)(1 << k); if ((encoder.possibleCrtcs & crtcMask) != 0) { uint crtcId = (uint)System.Runtime.InteropServices.Marshal.ReadInt32(resources.crtcs, k * sizeof(uint)); _drmEncoderCrtcId = crtcId; } } Drm.ModeFreeEncoder(encoderPtr); } break; } Drm.ModeFreeConnector(connectorPtr); } Drm.ModeFreeResources(resourcesPtr); Drm.SetClientCap(_drmFd, Drm.CLIENT_CAP_UNIVERSAL_PLANES, 1); _gbmDevice = Gbm.CreateDevice(_drmFd); _gbmSurface = Gbm.SurfaceCreate(_gbmDevice, (uint)_width, (uint)_height, Drm.FORMAT_ARGB8888, Gbm.BO_USE_SCANOUT | Gbm.BO_USE_RENDERING); _gbmBoToDrmFb = new Dictionary <IntPtr, uint>(); }