1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
// Copyright 2019 The Chromium Authors
// 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/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,
std::vector<viz::ReturnedResource> resources) override;
void OnBeginFramePausedChanged(bool paused) override;
void ReclaimResources(std::vector<viz::ReturnedResource> resources) override;
void OnCompositorFrameTransitionDirectiveProcessed(
uint32_t sequence_id) override {}
void OnSurfaceEvicted(const viz::LocalSurfaceId& local_surface_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_
|