chromium/services/viz/public/mojom/compositing/compositor_frame_sink.mojom

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

module viz.mojom;

import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/shared_memory.mojom";
import "services/viz/public/mojom/compositing/begin_frame_args.mojom";
import "services/viz/public/mojom/compositing/compositor_frame.mojom";
import "services/viz/public/mojom/compositing/layer_context.mojom";
import "services/viz/public/mojom/compositing/local_surface_id.mojom";
import "services/viz/public/mojom/compositing/frame_timing_details.mojom";
import "services/viz/public/mojom/compositing/returned_resource.mojom";
import "services/viz/public/mojom/compositing/shared_bitmap_id.mojom";
import "services/viz/public/mojom/hit_test/hit_test_region_list.mojom";

// Tags the frame sink with the type of source producing its content.
enum CompositorFrameSinkType {
  kUnspecified,
  kVideo,
  kMediaStream,
  kLayerTree,
};

// A CompositorFrameSink is an interface for receiving CompositorFrame
// structs. A CompositorFrame contains the complete output meant for display.
// Each time a client has a graphical update, and receives an OnBeginFrame, it
// is responsible for creating a CompositorFrame to update its portion of the
// screen.
interface CompositorFrameSink {
  // Lets the display compositor know that the client wishes to receive the next
  // BeginFrame event.
  SetNeedsBeginFrame(bool needs_begin_frame);

  // Lets the display compositor know that the client also wants to receive
  // BeginFrames with the animate_only flag set. Only clients that opt in
  // will receive such BeginFrames.
  SetWantsAnimateOnlyBeginFrames();

  // Lets the display compositor know that the client wants merged OnBeginFrame,
  // DidReceiveCompositorFrameAck, and ReclaimResources. Only supported when
  // features::OnBeginFrameAcks is enabled. Only clients that opt in will
  // receive such BeginFrames, others will still receive the signals separately.
  SetWantsBeginFrameAcks();

  // Lets the display compositor know that the client wants to use unsolicited
  // compositor frame submission to indicate that it wants to receive subsequent
  // BeginFrame events, as if SetNeedsBeginFrame(true) is called.
  SetAutoNeedsBeginFrame();

  // Submits a CompositorFrame to the display compositor that will be presented
  // to screen the next time frames from all CompositorFrameSinks are aggregated
  // to produce a display CompositorFrame. If a client wishes to allocate a new
  // surface (e.g. during resize), then it can simply allocate a new
  // |local_surface_id|. The local_id component of |local_surface_id| must be
  // monontonically increasing for each change to LocalSurfaceId. Submit time is
  // set to when this function is called to used for tracing how much time is
  // spend between a CompositorFrame is sent and received. Once a
  // |hit_test_region_list| is received, it will be reused until a new one is
  // submitted.
  // TODO(weiliangc): Submit time is recorded in microseconds right now and
  // should be changed to use TimeTicks when Blink can send base types directly.
  // For successful swaps, the implementation must call
  // DidReceiveCompositorFrameAck() asynchronously when the frame has been
  // processed in order to unthrottle the next frame.
  //
  // TODO(crbug.com/40154480): Investigate whether it's possible to alter the
  // CompositorFrame structure to be less likely to exceed soft message size
  // limits and remove [UnlimitedSize] here.
  [EstimateSize, UnlimitedSize]
  SubmitCompositorFrame(LocalSurfaceId local_surface_id,
                        CompositorFrame frame,
                        HitTestRegionList? hit_test_region_list,
                        uint64 submit_time);
  // Same as above, submits a CompositorFrame to the display compositor. The
  // implementation only returns when it's ready to receive another frame.
  // We also return the list of resources that would be returned by
  // DidReceiveCompositorFrameAck.
  [Sync] SubmitCompositorFrameSync(LocalSurfaceId local_surface_id,
                        CompositorFrame frame,
                        HitTestRegionList? hit_test_region_list,
                        uint64 submit_time)
                        => (array<ReturnedResource> resources);

  // Notifies the frame sink that a BeginFrame was completed, but that no
  // CompositorFrame was produced as a result of it.
  DidNotProduceFrame(BeginFrameAck ack);

  // Informs the display compositor that the client allocated a shared bitmap.
  // The |id| can then be used in subsequent CompositorFrames given to
  // SubmitCompositorFrame. The |id| is a SharedBitmapId.
  DidAllocateSharedBitmap(mojo_base.mojom.ReadOnlySharedMemoryRegion region,
                          SharedBitmapId id);

  // Informs the display compositor that the client deleted a shared bitmap. This
  // allows the service to free the shared memory that was previously given to it
  // via DidAllocateSharedBitmap(). The |id| is a SharedBitmapId.
  DidDeleteSharedBitmap(SharedBitmapId id);

  // This should be called atmost once for the lifetime of this frame sink. Once
  // the value has been set to anything other than kUnspecified, subsequent calls
  // are silently ignored.
  InitializeCompositorFrameSinkType(CompositorFrameSinkType type);

  // Binds to the LayerContext interface for this frame sink. Once this is bound
  // the frame sink is permanently in LayerContext mode and the client should no
  // longer submit frames through the CompositorFrameSink interface. Instead
  // frames will automtaically be submitted by Viz based on the state of a
  // GPU-side layer tree which can be manipulated through this LayerContext.
  BindLayerContext(PendingLayerContext context);

  // Informs the display compositor the IDs of the thread involved in frame
  // production. This is used on Android PerformanceHint API to dynamically
  // adjust performance to allow power saving.
  [EnableIf=is_android]
  SetThreadIds(array<int32> thread_ids);
};

interface CompositorFrameSinkClient {
  // Notification that the previous CompositorFrame given to
  // SubmitCompositorFrame() has been processed and that another frame
  // can be submitted. This provides backpressure from the display compositor
  // so that frames are submitted only at the rate it can handle them.
  // TODO(fsamuel): This method ought not be necessary with unified BeginFrame.
  // However, there's a fair amount of cleanup and refactoring necessary to get
  // rid of it.
  DidReceiveCompositorFrameAck(array<ReturnedResource> resources);

  // Notification for the client to generate a CompositorFrame. The client is
  // required to respond with either SubmitCompositorFrame() or
  // DidNotProduceFrame(). If the client is unresponsive then begin frames will
  // be throttled and eventually stopped entirely. We also return whether this
  // OnBeginFrame is to act as DidReceiveCompositorFrameAck. We also return a
  // list of resources, previously sent to SubmitCompositorFrame, to be reused
  // or freed.
  OnBeginFrame(BeginFrameArgs args,
               map<uint32, FrameTimingDetails> details,
               bool frame_ack,
               array<ReturnedResource> resources);

  // Inform the client that OnBeginFrame may not be called for some time.
  OnBeginFramePausedChanged(bool paused);

  // Returns resources sent to SubmitCompositorFrame to be reused or freed.
  ReclaimResources(array<ReturnedResource> resources);

  // Inform the client that a compositor frame transition directive was fully
  // processed.
  OnCompositorFrameTransitionDirectiveProcessed(uint32 sequence_id);

  // Inform the client that a Surface has been evicted. Upon eviction a client
  // should no longer submit to the given, or earlier, `local_surface_id`. This
  // will be followed later by a call to ReclaimResources for the previously
  // submitted CompositorFrame.
  OnSurfaceEvicted(LocalSurfaceId local_surface_id);
};