Пример #1
0
        public override Status Connect(IProducerListener listener, NativeWindowApi api, bool producerControlledByApp, out QueueBufferOutput output)
        {
            output = new QueueBufferOutput();

            lock (Core.Lock)
            {
                if (Core.IsAbandoned || Core.ConsumerListener == null)
                {
                    return(Status.NoInit);
                }

                if (Core.ConnectedApi != NativeWindowApi.NoApi)
                {
                    return(Status.BadValue);
                }

                Core.BufferHasBeenQueued      = false;
                Core.DequeueBufferCannotBlock = Core.ConsumerControlledByApp && producerControlledByApp;

                switch (api)
                {
                case NativeWindowApi.NVN:
                case NativeWindowApi.CPU:
                case NativeWindowApi.Media:
                case NativeWindowApi.Camera:
                    Core.ProducerListener = listener;
                    Core.ConnectedApi     = api;

                    output.Width             = (uint)Core.DefaultWidth;
                    output.Height            = (uint)Core.DefaultHeight;
                    output.TransformHint     = Core.TransformHint;
                    output.NumPendingBuffers = (uint)Core.Queue.Count;

                    if (NxSettings.Settings.TryGetValue("nv!nvn_no_vsync_capability", out object noVSyncCapability) && (bool)noVSyncCapability)
                    {
                        output.TransformHint |= NativeWindowTransform.NoVSyncCapability;
                    }

                    return(Status.Success);

                default:
                    return(Status.BadValue);
                }
            }
        }
 public abstract Status Connect(IProducerListener listener, NativeWindowApi api, bool producerControlledByApp, out QueueBufferOutput output);
 public abstract Status QueueBuffer(int slot, ref QueueBufferInput input, out QueueBufferOutput output);
Пример #4
0
        public override Status QueueBuffer(int slot, ref QueueBufferInput input, out QueueBufferOutput output)
        {
            output = default;

            switch (input.ScalingMode)
            {
            case NativeWindowScalingMode.Freeze:
            case NativeWindowScalingMode.ScaleToWindow:
            case NativeWindowScalingMode.ScaleCrop:
            case NativeWindowScalingMode.Unknown:
            case NativeWindowScalingMode.NoScaleCrop:
                break;

            default:
                return(Status.BadValue);
            }

            BufferItem item = new BufferItem();

            IConsumerListener frameAvailableListener = null;
            IConsumerListener frameReplaceListener   = null;

            lock (Core.Lock)
            {
                if (Core.IsAbandoned)
                {
                    return(Status.NoInit);
                }

                int maxBufferCount = Core.GetMaxBufferCountLocked(input.Async != 0);

                if (input.Async != 0 && Core.OverrideMaxBufferCount != 0 && Core.OverrideMaxBufferCount < maxBufferCount)
                {
                    return(Status.BadValue);
                }

                if (slot < 0 || slot >= Core.Slots.Length || !Core.IsOwnedByProducerLocked(slot))
                {
                    return(Status.BadValue);
                }

                if (!Core.Slots[slot].RequestBufferCalled)
                {
                    Logger.PrintError(LogClass.SurfaceFlinger, $"Slot {slot} was queued without requesting a buffer");

                    return(Status.BadValue);
                }

                input.Crop.Intersect(Core.Slots[slot].GraphicBuffer.Object.ToRect(), out Rect croppedRect);

                if (croppedRect != input.Crop)
                {
                    return(Status.BadValue);
                }

                Core.Slots[slot].Fence       = input.Fence;
                Core.Slots[slot].BufferState = BufferState.Queued;
                Core.FrameCounter++;
                Core.Slots[slot].FrameNumber      = Core.FrameCounter;
                Core.Slots[slot].QueueTime        = TimeSpanType.FromTimeSpan(ARMeilleure.State.ExecutionContext.ElapsedTime);
                Core.Slots[slot].PresentationTime = TimeSpanType.Zero;

                item.AcquireCalled             = Core.Slots[slot].AcquireCalled;
                item.Crop                      = input.Crop;
                item.Transform                 = input.Transform;
                item.TransformToDisplayInverse = (input.Transform & NativeWindowTransform.InverseDisplay) == NativeWindowTransform.InverseDisplay;
                item.ScalingMode               = input.ScalingMode;
                item.Timestamp                 = input.Timestamp;
                item.IsAutoTimestamp           = input.IsAutoTimestamp != 0;
                item.SwapInterval              = input.SwapInterval;
                item.FrameNumber               = Core.FrameCounter;
                item.Slot                      = slot;
                item.Fence                     = input.Fence;
                item.IsDroppable               = Core.DequeueBufferCannotBlock || input.Async != 0;

                item.GraphicBuffer.Set(Core.Slots[slot].GraphicBuffer);
                item.GraphicBuffer.Object.IncrementNvMapHandleRefCount(Core.Owner);

                Core.BufferHistoryPosition = (Core.BufferHistoryPosition + 1) % BufferQueueCore.BufferHistoryArraySize;

                Core.BufferHistory[Core.BufferHistoryPosition] = new BufferInfo
                {
                    FrameNumber = Core.FrameCounter,
                    QueueTime   = Core.Slots[slot].QueueTime,
                    State       = BufferState.Queued
                };

                _stickyTransform = input.StickyTransform;

                if (Core.Queue.Count == 0)
                {
                    Core.Queue.Add(item);

                    frameAvailableListener = Core.ConsumerListener;
                }
                else
                {
                    BufferItem frontItem = Core.Queue[0];

                    if (frontItem.IsDroppable)
                    {
                        if (Core.StillTracking(ref frontItem))
                        {
                            Core.Slots[slot].BufferState = BufferState.Free;
                            Core.Slots[slot].FrameNumber = 0;
                        }

                        Core.Queue.RemoveAt(0);
                        Core.Queue.Insert(0, item);

                        frameReplaceListener = Core.ConsumerListener;
                    }
                    else
                    {
                        Core.Queue.Add(item);

                        frameAvailableListener = Core.ConsumerListener;
                    }
                }

                Core.BufferHasBeenQueued = true;
                Core.SignalDequeueEvent();

                Core.CheckSystemEventsLocked(maxBufferCount);

                output = new QueueBufferOutput
                {
                    Width             = (uint)Core.DefaultWidth,
                    Height            = (uint)Core.DefaultHeight,
                    TransformHint     = Core.TransformHint,
                    NumPendingBuffers = (uint)Core.Queue.Count
                };

                _callbackTicket = _nextCallbackTicket++;
            }

            lock (_callbackLock)
            {
                while (_callbackTicket != _currentCallbackTicket)
                {
                    Monitor.Wait(_callbackLock);
                }

                frameAvailableListener?.OnFrameAvailable(ref item);
                frameReplaceListener?.OnFrameReplaced(ref item);

                _currentCallbackTicket++;

                Monitor.PulseAll(_callbackLock);
            }

            return(Status.Success);
        }