コード例 #1
0
        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);
            }
        }
コード例 #2
0
        public override void Update(IWindowInfo window)
        {
            WaitFlip(true);

            base.SwapBuffers();

            bo = LockSurface();
            int fb = GetFramebuffer(bo);

            SetScanoutRegion(fb);
        }
コード例 #3
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);
            }
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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;
            }
        }
コード例 #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);
        }
コード例 #7
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;
        }
コード例 #8
0
 public static extern void ReleaseBuffer(Surface surface, BufferObject buffer);
コード例 #9
0
 public static extern void DestroyBuffer(BufferObject bo);