示例#1
0
        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);
                }
            }
        }
示例#2
0
 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);
 }
示例#3
0
        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);
        }
示例#4
0
        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);
            }
        }
示例#5
0
        /// \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);
            }
        }
示例#6
0
 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);
     }
 }
示例#7
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);
            }
        }
示例#8
0
        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);
            }
        }
示例#9
0
 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);
     }
 }
示例#10
0
 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);
     }
 }
示例#11
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);
        }
示例#12
0
        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);
        }
示例#13
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;
            }
        }
示例#14
0
        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;
            }
        }