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);
            }
        }
Beispiel #3
0
 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);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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));
        }
Beispiel #9
0
        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);
 }