private void SetScanoutRegion(int buffer) { LinuxWindowInfo wnd = WindowInfo as LinuxWindowInfo; if (wnd == null) { throw new InvalidOperationException(); } unsafe { ModeInfo *mode = wnd.DisplayDevice.pConnector->modes; int connector_id = wnd.DisplayDevice.pConnector->connector_id; int crtc_id = wnd.DisplayDevice.Id; int x = 0; int y = 0; int connector_count = 1; int ret = Drm.ModeSetCrtc(fd, crtc_id, buffer, x, y, &connector_id, connector_count, mode); if (ret != 0) { Debug.Print("[KMS] Drm.ModeSetCrtc{0}, {1}, {2}, {3}, {4:x}, {5}, {6:x}) failed. Error: {7}", fd, crtc_id, buffer, x, y, (IntPtr)connector_id, connector_count, (IntPtr)mode, ret); } } }
protected override void Dispose(bool manual) { if (manual) { // Reset the scanout region LinuxWindowInfo wnd = WindowInfo as LinuxWindowInfo; if (wnd != null) { unsafe { int connector_id = wnd.DisplayDevice.pConnector->connector_id; ModeInfo mode = wnd.DisplayDevice.OriginalMode; Drm.ModeSetCrtc(fd, wnd.DisplayDevice.pCrtc->crtc_id, wnd.DisplayDevice.pCrtc->buffer_id, wnd.DisplayDevice.pCrtc->x, wnd.DisplayDevice.pCrtc->y, &connector_id, 1, &mode); } } } base.Dispose(manual); }
private unsafe static ModeEncoder *GetEncoder(int fd, ModeConnector *c) { ModeEncoder *encoder = null; for (int i = 0; i < c->count_encoders && encoder == null; i++) { ModeEncoder *e = (ModeEncoder *)Drm.ModeGetEncoder( fd, *(c->encoders + i)); if (e != null) { if (e->encoder_id == c->encoder_id) { encoder = e; } else { Drm.ModeFreeEncoder((IntPtr)e); } } } if (encoder != null) { Debug.Print("[KMS] Encoder {0} found for connector {1}", encoder->encoder_id, c->connector_id); } else { Debug.Print("[KMS] Failed to find encoder for connector {0}", c->connector_id); } return(encoder); }
private void SetCursor(MouseCursor cursor) { BufferObject bo = default(BufferObject); if (cursor == MouseCursor.Default) { bo = cursor_default; } else if (cursor == MouseCursor.Empty) { bo = cursor_empty; } else { if (cursor_custom != BufferObject.Zero) { cursor_custom.Dispose(); } cursor_custom = CreateCursor(window.BufferManager, cursor); bo = cursor_custom; } // If we failed to create a proper cursor, try falling back // to the empty cursor. We do not want to crash here! if (bo == BufferObject.Zero) { bo = cursor_empty; } if (bo != BufferObject.Zero) { Drm.SetCursor(window.FD, window.DisplayDevice.Id, bo.Handle, bo.Width, bo.Height, cursor.X, cursor.Y); } }
/// \internal /// <summary> /// Queries the specified GPU for connected displays and, optionally, /// returns the list of displays. /// </summary> /// <returns><c>true</c>, if at least one display is connected, <c>false</c> otherwise.</returns> /// <param name="fd">The fd for the GPU to query, obtained through open("/dev/dri/card0").</param> /// <param name="displays"> /// If not null, this will contain a list <see cref="LinuxDisplay"/> instances, /// one for each connected display. /// </param> internal static bool QueryDisplays(int fd, List <LinuxDisplay> displays) { unsafe { bool has_displays = false; if (displays != null) { displays.Clear(); } ModeRes *resources = (ModeRes *)Drm.ModeGetResources(fd); if (resources == null) { Debug.Print("[KMS] Drm.ModeGetResources failed."); return(false); } Debug.Print("[KMS] DRM found {0} connectors", resources->count_connectors); // Search for a valid connector ModeConnector *connector = null; for (int i = 0; i < resources->count_connectors; i++) { connector = (ModeConnector *)Drm.ModeGetConnector(fd, *(resources->connectors + i)); if (connector != null) { bool success = false; LinuxDisplay display = null; try { if (connector->connection == ModeConnection.Connected && connector->count_modes > 0) { success = QueryDisplay(fd, connector, out display); has_displays |= success; } } catch (Exception e) { Debug.Print("[KMS] Failed to add display. Error: {0}", e); } if (success && displays != null) { displays.Add(display); } else { Drm.ModeFreeConnector((IntPtr)connector); connector = null; } } } return(has_displays); } }
public override bool TryRestoreResolution(DisplayDevice device) { unsafe { LinuxDisplay display = (LinuxDisplay)device.Id; ModeInfo mode = display.OriginalMode; int connector_id = display.pConnector->connector_id; return(Drm.ModeSetCrtc(FD, display.Id, 0, 0, 0, &connector_id, 1, &mode) == 0); } }
private static void HandleDestroyFB(BufferObject bo, IntPtr data) { IntPtr gbm = bo.Device; int fb = data.ToInt32(); Debug.Print("[KMS] Destroying framebuffer {0}", fb); if (fb != 0) { Drm.ModeRmFB(Gbm.DeviceGetFD(gbm), fb); } }
private void UpdateCursor() { Point p = new Point( (int)Math.Round(CursorPosition.X + CursorOffset.X), (int)Math.Round(CursorPosition.Y + CursorOffset.Y)); DisplayDevice display = DisplayDevice.FromPoint(p.X, p.Y) ?? DisplayDevice.Default; if (display != null) { LinuxDisplay d = (LinuxDisplay)display.Id; Drm.MoveCursor(d.FD, d.Id, p.X, p.Y); } }
protected override void Dispose(bool disposing) { if (disposing) { Debug.Print("[KMS] Destroying window {0}.", window.Handle); Drm.SetCursor(window.FD, window.DisplayDevice.Id, 0, 0, 0, 0, 0); window.Dispose(); Gbm.DestroySurface(window.Handle); } else { Debug.Print("[KMS] {0} leaked. Did you forget to call Dispose()?", GetType().FullName); } }
public override bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution) { unsafe { LinuxDisplay display = (LinuxDisplay)device.Id; ModeInfo * mode = GetModeInfo(display, resolution); int connector_id = display.pConnector->connector_id; if (mode != null) { return(Drm.ModeSetCrtc(FD, display.Id, 0, 0, 0, &connector_id, 1, mode) == 0); } return(false); } }
private int GetFramebuffer(BufferObject bo) { if (bo == BufferObject.Zero) { goto fail; } int bo_handle = bo.Handle; if (bo_handle == 0) { Debug.Print("[KMS] Gbm.BOGetHandle({0:x}) failed.", bo); goto fail; } int width = bo.Width; int height = bo.Height; int bpp = Mode.ColorFormat.BitsPerPixel; int depth = Mode.Depth; int stride = bo.Stride; if (width == 0 || height == 0 || bpp == 0) { Debug.Print("[KMS] Invalid framebuffer format: {0}x{1} {2} {3} {4}", width, height, stride, bpp, depth); goto fail; } int buffer; int ret = Drm.ModeAddFB( fd, width, height, (byte)depth, (byte)bpp, stride, bo_handle, out buffer); if (ret != 0) { Debug.Print("[KMS] Drm.ModeAddFB({0}, {1}, {2}, {3}, {4}, {5}, {6}) failed. Error: {7}", fd, width, height, depth, bpp, stride, bo_handle, ret); goto fail; } bo.SetUserData((IntPtr)buffer, DestroyFB); return(buffer); fail: Debug.Print("[Error] Failed to create framebuffer."); return(-1); }
private unsafe static ModeCrtc *GetCrtc(int fd, ModeEncoder *encoder) { ModeCrtc *crtc = (ModeCrtc *)Drm.ModeGetCrtc(fd, encoder->crtc_id); if (crtc != null) { Debug.Print("[KMS] CRTC {0} found for encoder {1}", encoder->crtc_id, encoder->encoder_id); } else { Debug.Print("[KMS] Failed to find crtc {0} for encoder {1}", encoder->crtc_id, encoder->encoder_id); } return(crtc); }
private void WaitFlip(bool block) { PollFD fds = new PollFD(); fds.fd = fd; fds.events = PollFlags.In; EventContext evctx = new EventContext(); evctx.version = EventContext.Version; evctx.page_flip_handler = PageFlipPtr; int timeout = block ? -1 : 0; while (is_flip_queued) { fds.revents = 0; if (Libc.poll(ref fds, 1, timeout) < 0) { break; } if ((fds.revents & (PollFlags.Hup | PollFlags.Error)) != 0) { break; } if ((fds.revents & PollFlags.In) != 0) { Drm.HandleEvent(fd, ref evctx); } else { break; } } // Page flip has taken place, update buffer objects if (!is_flip_queued) { IntPtr gbm_surface = WindowInfo.Handle; Gbm.ReleaseBuffer(gbm_surface, bo); bo = bo_next; } }
private void QueueFlip(int buffer) { LinuxWindowInfo wnd = WindowInfo as LinuxWindowInfo; if (wnd == null) { throw new InvalidOperationException(); } unsafe { int ret = Drm.ModePageFlip(fd, wnd.DisplayDevice.Id, buffer, PageFlipFlags.FlipEvent, IntPtr.Zero); if (ret < 0) { Debug.Print("[KMS] Failed to enqueue framebuffer flip. Error: {0}", ret); } is_flip_queued = true; } }