public virtual void OnFrameAvailable(ref BufferItem item) { _listener?.OnFrameAvailable(ref item); }
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); }