Пример #1
0
        private static int GetLevel(IVncServerSession vncServerSession, VncEncoding lower, VncEncoding upper, int defaultValue)
        {
            if (vncServerSession?.ClientEncodings == null)
            {
                return(defaultValue);
            }

            foreach (var encoding in vncServerSession.ClientEncodings)
            {
                if (encoding >= lower && encoding <= upper)
                {
                    return(encoding - lower);
                }
            }

            return(defaultValue);
        }
Пример #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TightEncoder"/> class.
 /// </summary>
 /// <param name="vncServerSession">
 /// The parent session to which this <see cref="TightEncoder"/> is linked.
 /// </param>
 public TightEncoder(IVncServerSession vncServerSession)
 {
     this.VncServerSession = vncServerSession ?? throw new ArgumentNullException(nameof(vncServerSession));
 }
Пример #3
0
 /// <summary>
 /// Gets the zlib compression level to use.
 /// </summary>
 /// <param name="vncServerSession">
 /// The current VNC server session.
 /// </param>
 /// <returns>
 /// The <see cref="CompressionLevel"/> to use for zlib streams for this session.
 /// </returns>
 public static CompressionLevel GetCompressionLevel(IVncServerSession vncServerSession)
 {
     return((CompressionLevel)GetLevel(vncServerSession, VncEncoding.TightCompressionLevel0, VncEncoding.TightCompressionLevel9, (int)CompressionLevel.Default));
 }
Пример #4
0
 /// <summary>
 /// Gets the JPEG quality level to use.
 /// </summary>
 /// <param name="vncServerSession">
 /// The current VNC server session.
 /// </param>
 /// <returns>
 /// The JPEG quality level to use, or 0 when JPEG compression should be disabled.
 /// </returns>
 public static int GetQualityLevel(IVncServerSession vncServerSession)
 {
     return(QualityLevels[GetLevel(vncServerSession, VncEncoding.TightQualityLevel0, VncEncoding.TightQualityLevel9, 10)]);
 }
Пример #5
0
        /// <summary>
        /// Responds to a <see cref="VncServerSession"/> update request.
        /// </summary>
        /// <param name="session">
        /// The session on which the update request was received.
        /// </param>
        /// <returns>
        /// <see langword="true"/> if the operation completed successfully; otherwise,
        /// <see langword="false"/>.
        /// </returns>
        public unsafe bool RespondToUpdateRequest(IVncServerSession session)
        {
            VncRectangle subregion = default(VncRectangle);

            var fb  = this.Framebuffer;
            var fbr = session.FramebufferUpdateRequest;

            if (fb == null || fbr == null)
            {
                return(false);
            }

            var incremental = fbr.Incremental;
            var region      = fbr.Region;
            int bpp         = fb.PixelFormat.BytesPerPixel;

            this.logger?.Log(LogLevel.Debug, () => $"Responding to an update request for region {region}.");

            session.FramebufferManualBeginUpdate();

            // Take a lock here, as we will modify
            // both buffers heavily in the next block.
            lock (fb.SyncRoot)
            {
                lock (this.cachedFramebuffer.SyncRoot)
                {
                    var actualBuffer   = this.Framebuffer.GetBuffer();
                    var bufferedBuffer = this.cachedFramebuffer.GetBuffer();

                    // In this block, we will determine which rectangles need updating. Right now, we consider
                    // each line at once. It's not a very efficient algorithm, but it works.
                    // We're going to start at the upper-left position of the region, and then we will work our way down,
                    // on a line by line basis, to determine if each line is still valid.
                    // isLineInvalid will indicate, on a line-by-line basis, whether a line is still valid or not.
                    for (int y = region.Y; y < region.Y + region.Height; y++)
                    {
                        subregion.X      = region.X;
                        subregion.Y      = y;
                        subregion.Width  = region.Width;
                        subregion.Height = 1;

                        // For a given y, the x pixels are stored sequentially in the array
                        // starting at y * stride (number of bytes per row); for each x
                        // value there are bpp bytes of data (4 for a 32-bit integer); we are looking
                        // for pixels between x and x + w so this translates to
                        // y * stride + bpp * x and y * stride + bpp * (x + w)
                        int srcOffset = (y * this.Framebuffer.Stride) + (bpp * region.X);
                        int length    = bpp * region.Width;

                        var isValid = actualBuffer.AsSpan().Slice(srcOffset, length)
                                      .SequenceCompareTo(bufferedBuffer.AsSpan().Slice(srcOffset, length)) == 0;

                        if (!isValid)
                        {
                            try
                            {
                                Buffer.BlockCopy(actualBuffer, srcOffset, bufferedBuffer, srcOffset, length);
                            }
                            catch
                            {
                                throw;
                            }
                        }

                        this.isLineInvalid[y - region.Y] = !isValid;
                    }
                } // lock
            }     // lock

            if (incremental)
            {
                // Determine logical group of lines which are invalid. We find the first line which is invalid,
                // create a new region which contains the all invalid lines which immediately follow the current line.
                // If we find a valid line, we'll create a new region.
                int?y = null;

                for (int line = 0; line < region.Height; line++)
                {
                    if (y == null && this.isLineInvalid[line])
                    {
                        y = region.Y + line;
                    }

                    if (y != null && (!this.isLineInvalid[line] || line == region.Height - 1))
                    {
                        // Flush
                        subregion.X      = region.X;
                        subregion.Y      = region.Y + y.Value;
                        subregion.Width  = region.Width;
                        subregion.Height = line - y.Value + 1;
                        session.FramebufferManualInvalidate(subregion);
                        y = null;
                    }
                }
            }
            else
            {
                session.FramebufferManualInvalidate(region);
            }

            return(session.FramebufferManualEndUpdate());
        }