public int Write(byte[] data) { unsafe { fixed(byte *pdata = data) { return(Gbm.BOWrite(buffer, (IntPtr)pdata, (IntPtr)data.Length)); } } }
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); } }
protected override void Dispose(bool disposing) { if (disposing) { Debug.Print("[KMS] Destroying window {0}.", window.Handle); window.Dispose(); Gbm.DestroySurface(window.Handle); } else { Debug.Print("[KMS] {0} leaked. Did you forget to call Dispose()?", GetType().FullName); } }
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 static int SetupDisplay(string gpu, out IntPtr gbm_device, out IntPtr egl_display) { Debug.Print("[KMS] Attempting to use gpu '{0}'.", gpu); gbm_device = IntPtr.Zero; egl_display = IntPtr.Zero; var fd = Libc.open(gpu, OpenFlags.ReadWrite | OpenFlags.CloseOnExec); if (fd < 0) { Debug.Print("[KMS] Failed to open gpu"); return(fd); } Debug.Print("[KMS] GPU '{0}' opened as fd:{1}", gpu, fd); gbm_device = Gbm.CreateDevice(fd); if (gbm_device == IntPtr.Zero) { throw new NotSupportedException("[KMS] Failed to create GBM device"); } Debug.Print("[KMS] GBM {0:x} created successfully; ", gbm_device); egl_display = Egl.Egl.GetDisplay(gbm_device); if (egl_display == IntPtr.Zero) { throw new NotSupportedException("[KMS] Failed to create EGL display"); } Debug.Print("[KMS] EGL display {0:x} created successfully", egl_display); int major, minor; if (!Egl.Egl.Initialize(egl_display, out major, out minor)) { var error = Egl.Egl.GetError(); throw new NotSupportedException("[KMS] Failed to initialize EGL display. Error code: " + error); } Debug.Print("[KMS] EGL {0}.{1} initialized successfully on display {2:x}", major, minor, egl_display); return(fd); }
static BufferObject CreateCursor(IntPtr gbm, MouseCursor cursor) { if (cursor.Width > 64 || cursor.Height > 64) { Debug.Print("[KMS] Cursor size {0}x{1} unsupported. Maximum is 64x64.", cursor.Width, cursor.Height); return(default(BufferObject)); } int width = 64; int height = 64; SurfaceFormat format = SurfaceFormat.ARGB8888; SurfaceFlags usage = SurfaceFlags.Cursor64x64 | SurfaceFlags.Write; Debug.Print("[KMS] Gbm.CreateBuffer({0:X}, {1}, {2}, {3}, {4}).", gbm, width, height, format, usage); BufferObject bo = Gbm.CreateBuffer( gbm, width, height, format, usage); if (bo == BufferObject.Zero) { Debug.Print("[KMS] Failed to create buffer."); return(bo); } // Copy cursor.Data into a new buffer of the correct size byte[] cursor_data = new byte[width * height * 4]; for (int y = 0; y < cursor.Height; y++) { int dst_offset = y * width * 4; int src_offset = y * cursor.Width * 4; int src_length = cursor.Width * 4; Array.Copy( cursor.Data, src_offset, cursor_data, dst_offset, src_length); } bo.Write(cursor_data); return(bo); }
protected override void Dispose(bool manual) { if (egl_display != IntPtr.Zero) { Debug.Print("[KMS] Terminating EGL."); Egl.Terminate(egl_display); egl_display = IntPtr.Zero; } if (gbm_device != IntPtr.Zero) { Debug.Print("[KMS] Destroying GBM device."); Gbm.DestroyDevice(gbm_device); gbm_device = IntPtr.Zero; } if (_fd >= 0) { Debug.Print("[KMS] Closing GPU fd."); Libc.close(_fd); } base.Dispose(manual); }
private BufferObject LockSurface() { IntPtr gbm_surface = WindowInfo.Handle; return(Gbm.LockFrontBuffer(gbm_surface)); }
public LinuxNativeWindow(IntPtr display, IntPtr gbm, int fd, int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice display_device) { Debug.Print("[KMS] Creating window on display {0:x}", display); Title = title; display_device = display_device ?? DisplayDevice.Default; if (display_device == null) { throw new NotSupportedException("[KMS] Driver does not currently support headless systems"); } window = new LinuxWindowInfo(display, fd, gbm, display_device.Id as LinuxDisplay); // Note: we only support fullscreen windows on KMS. // We implicitly override the requested width and height // by the width and height of the DisplayDevice, if any. width = display_device.Width; height = display_device.Height; bounds = new Rectangle(0, 0, width, height); client_size = bounds.Size; if (!mode.Index.HasValue) { mode = new EglGraphicsMode().SelectGraphicsMode(window, mode, 0); } Debug.Print("[KMS] Selected EGL mode {0}", mode); SurfaceFormat format = GetSurfaceFormat(display, mode); SurfaceFlags usage = SurfaceFlags.Rendering | SurfaceFlags.Scanout; if (!Gbm.IsFormatSupported(gbm, format, usage)) { Debug.Print("[KMS] Failed to find suitable surface format, using XRGB8888"); format = SurfaceFormat.XRGB8888; } Debug.Print("[KMS] Creating GBM surface on {0:x} with {1}x{2} {3} [{4}]", gbm, width, height, format, usage); IntPtr gbm_surface = Gbm.CreateSurface(gbm, width, height, format, usage); if (gbm_surface == IntPtr.Zero) { throw new NotSupportedException("[KMS] Failed to create GBM surface for rendering"); } window.Handle = gbm_surface; Debug.Print("[KMS] Created GBM surface {0:x}", window.Handle); window.CreateWindowSurface(mode.Index.Value); Debug.Print("[KMS] Created EGL surface {0:x}", window.Surface); cursor_default = CreateCursor(gbm, Cursors.Default); cursor_empty = CreateCursor(gbm, Cursors.Empty); Cursor = MouseCursor.Default; exists = true; }
public void Dispose() { Gbm.DestroyBuffer(this); buffer = IntPtr.Zero; }
public void SetUserData(IntPtr data, DestroyUserDataCallback destroyFB) { Gbm.BOSetUserData(buffer, data, destroyFB); }