blob: 5d1631a33b2f6c8cfb1a15b719af8dcc4e2eecff [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_VIZ_DEMO_CLIENT_DEMO_CLIENT_H_
#define COMPONENTS_VIZ_DEMO_CLIENT_DEMO_CLIENT_H_
#include <map>
#include <vector>
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "components/viz/common/presentation_feedback_map.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
namespace viz {
class CompositorFrame;
}
namespace demo {
// DemoClient is responsible for communicating with the display-compositor. It
// sends messages to the service over the mojom.CompositorFrameSink interface,
// and receives messages through the mojom.CompositorFrameSinkClient interface.
//
// The client needs to have an identifier, FrameSinkId, which doesn't change
// during the lifetime of the client. The embedder of the client needs to know
// about this FrameSinkId. The 'host', when it itself is not the embedder, also
// needs to know about this FrameSinkId, so that it can set up the
// frame-hierarchy correctly in the service.
//
// The client also needs to have a LocalSurfaceId, which represents an embedding
// of the client in a particular state. If, for example, the size of the client
// changes (or other attributes, like device scale factor), then a new
// LocalSurfaceId needs to be allocated. The LocalSurfaceId is used to submit
// the CompositorFrame. Both the embedder and the embedded clients need to know
// the LocalSurfaceId. It is possible for both the embedder and the embedded
// client to generate new LocalSurfaceId (typically using a
// ParentLocalSurfaceIdAllocator and ChildLocalSurfaceIdAllocator respectively).
// In this demo, only the embedder allocates the LocalSurfaceId.
class DemoClient : public viz::mojom::CompositorFrameSinkClient {
public:
DemoClient(const viz::FrameSinkId& frame_sink_id,
const viz::LocalSurfaceIdAllocation& local_surface_id,
const gfx::Rect& bounds);
~DemoClient() override;
const viz::FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
// Initializes the mojo connection to the service.
void Initialize(viz::mojom::CompositorFrameSinkClientRequest request,
viz::mojom::CompositorFrameSinkAssociatedPtrInfo sink_info);
void Initialize(viz::mojom::CompositorFrameSinkClientRequest request,
viz::mojom::CompositorFrameSinkPtrInfo sink_info);
// This prepares for this client to embed another client (i.e. this client
// acts as the embedder). Since this client is the embedder, it allocates the
// LocalSurfaceId, and returns that. The client that should be embedded (i.e.
// the client represented by |frame_sink_id|) should use the returned
// LocalSurfaceId to submit visual content (CompositorFrame).
viz::LocalSurfaceIdAllocation Embed(const viz::FrameSinkId& frame_sink_id,
const gfx::Rect& bounds);
// When this client is resized, it is important that it also receives a new
// LocalSurfaceId with the new size.
void Resize(const gfx::Size& size,
const viz::LocalSurfaceIdAllocation& local_surface_id);
private:
struct EmbedInfo {
viz::LocalSurfaceIdAllocation lsid;
gfx::Rect bounds;
float degrees = 0.f;
};
viz::CompositorFrame CreateFrame(const viz::BeginFrameArgs& args)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
viz::mojom::CompositorFrameSink* GetPtr();
void InitializeOnThread(
viz::mojom::CompositorFrameSinkClientRequest request,
viz::mojom::CompositorFrameSinkAssociatedPtrInfo associated_sink_info,
viz::mojom::CompositorFrameSinkPtrInfo sink_info);
// viz::mojom::CompositorFrameSinkClient:
void DidReceiveCompositorFrameAck(
const std::vector<viz::ReturnedResource>& resources) override;
void OnBeginFrame(const viz::BeginFrameArgs& args,
const viz::PresentationFeedbackMap& feedbacks) override;
void OnBeginFramePausedChanged(bool paused) override;
void ReclaimResources(
const std::vector<viz::ReturnedResource>& resources) override;
// This thread is created solely to demonstrate that the client can live in
// its own thread (or even in its own process). A viz client does not need to
// have its own thread.
base::Thread thread_;
const viz::FrameSinkId frame_sink_id_;
viz::LocalSurfaceIdAllocation local_surface_id_ GUARDED_BY(lock_);
gfx::Rect bounds_ GUARDED_BY(lock_);
mojo::Binding<viz::mojom::CompositorFrameSinkClient> binding_;
viz::mojom::CompositorFrameSinkAssociatedPtr associated_sink_;
viz::mojom::CompositorFrameSinkPtr sink_;
viz::FrameTokenGenerator next_frame_token_;
uint32_t frame_count_ = 0;
base::Lock lock_;
// The |allocator_| is used only when this client acts as an embedder, and
// embeds other clients.
viz::ParentLocalSurfaceIdAllocator allocator_;
std::map<viz::FrameSinkId, EmbedInfo> embeds_ GUARDED_BY(lock_);
DISALLOW_COPY_AND_ASSIGN(DemoClient);
};
} // namespace demo
#endif // COMPONENTS_VIZ_DEMO_CLIENT_DEMO_CLIENT_H_