[go: nahoru, domu]

blob: f86f05b5b796d2604e3b7d9bd5f2e8e74f88b863 [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 "base/time/time.h"
#include "components/viz/common/frame_timing_details_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/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/viz/public/mojom/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::LocalSurfaceId& local_surface_id,
const gfx::Rect& bounds);
DemoClient(const DemoClient&) = delete;
DemoClient& operator=(const DemoClient&) = delete;
~DemoClient() override;
const viz::FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
// Initializes the mojo connection to the service.
void Initialize(
mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> receiver,
mojo::PendingAssociatedRemote<viz::mojom::CompositorFrameSink>
sink_remote);
void Initialize(
mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> receiver,
mojo::PendingRemote<viz::mojom::CompositorFrameSink> sink_remote);
// 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::LocalSurfaceId 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::LocalSurfaceId& local_surface_id);
private:
struct EmbedInfo {
viz::LocalSurfaceId 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(
mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> receiver,
mojo::PendingAssociatedRemote<viz::mojom::CompositorFrameSink>
associated_sink_remote,
mojo::PendingRemote<viz::mojom::CompositorFrameSink> sink_remote);
// viz::mojom::CompositorFrameSinkClient:
void DidReceiveCompositorFrameAck(
std::vector<viz::ReturnedResource> resources) override;
void OnBeginFrame(const viz::BeginFrameArgs& args,
const viz::FrameTimingDetailsMap& timing_details) override;
void OnBeginFramePausedChanged(bool paused) override;
void ReclaimResources(std::vector<viz::ReturnedResource> resources) override;
void OnCompositorFrameTransitionDirectiveProcessed(
uint32_t sequence_id) 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::LocalSurfaceId local_surface_id_ GUARDED_BY(lock_);
gfx::Rect bounds_ GUARDED_BY(lock_);
mojo::Receiver<viz::mojom::CompositorFrameSinkClient> receiver_{this};
mojo::AssociatedRemote<viz::mojom::CompositorFrameSink> associated_sink_;
mojo::Remote<viz::mojom::CompositorFrameSink> 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_);
};
} // namespace demo
#endif // COMPONENTS_VIZ_DEMO_CLIENT_DEMO_CLIENT_H_