#ifndef GPU_IPC_CLIENT_GPU_CHANNEL_HOST_H_
#define GPU_IPC_CLIENT_GPU_CHANNEL_HOST_H_
#include <stddef.h>
#include <stdint.h>
#include <atomic>
#include <memory>
#include <vector>
#include "base/atomic_sequence_num.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/rand_util.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_info.h"
#include "gpu/ipc/client/gpu_channel_observer.h"
#include "gpu/ipc/client/gpu_ipc_client_export.h"
#include "gpu/ipc/client/shared_image_interface_proxy.h"
#include "gpu/ipc/common/gpu_channel.mojom.h"
#include "ipc/ipc_listener.h"
#include "mojo/public/cpp/base/shared_memory_version.h"
#include "mojo/public/cpp/bindings/shared_associated_remote.h"
#include "ui/gfx/gpu_memory_buffer_handle.h"
#include "arkweb/chromium_ext/gpu/ipc/client/gpu_channel_host_utils.h"
namespace IPC {
class Channel;
}
namespace gpu {
class SharedImageInterface;
struct SyncToken;
class GpuChannelHost;
class GpuChannelHostUtils;
using GpuChannelEstablishedCallback =
base::OnceCallback<void(scoped_refptr<GpuChannelHost>)>;
class GPU_IPC_CLIENT_EXPORT GpuChannelEstablishFactory {
public:
virtual ~GpuChannelEstablishFactory() = default;
virtual void EstablishGpuChannel(GpuChannelEstablishedCallback callback) = 0;
virtual scoped_refptr<GpuChannelHost> EstablishGpuChannelSync() = 0;
};
class GPU_IPC_CLIENT_EXPORT GpuChannelHost
: public base::RefCountedThreadSafe<GpuChannelHost> {
public:
friend class GpuChannelHostUtils;
GpuChannelHost(
int channel_id,
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
const gpu::SharedImageCapabilities& shared_image_capabilities,
mojo::ScopedMessagePipeHandle handle,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner = nullptr);
GpuChannelHost(const GpuChannelHost&) = delete;
GpuChannelHost& operator=(const GpuChannelHost&) = delete;
bool IsLost() const { return !connection_tracker_->is_connected(); }
int channel_id() const { return channel_id_; }
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner() {
return io_thread_;
}
virtual mojom::GpuChannel& GetGpuChannel();
const gpu::GPUInfo& gpu_info() const { return gpu_info_; }
const gpu::GpuFeatureInfo& gpu_feature_info() const {
return gpu_feature_info_;
}
uint32_t OrderingBarrier(int32_t route_id,
int32_t put_offset,
std::vector<SyncToken> sync_token_fences,
uint64_t release_count);
uint32_t EnqueueDeferredMessage(mojom::DeferredRequestParamsPtr params,
std::vector<SyncToken> sync_token_fences,
uint64_t release_count);
virtual void EnsureFlush(uint32_t deferred_message_id);
virtual void DelayedEnsureFlush(uint32_t deferred_message_id);
void VerifyFlush(uint32_t deferred_message_id);
void DestroyChannel();
int32_t ReserveImageId();
int32_t GenerateRouteID();
void CreateGpuMemoryBuffer(const gfx::Size& size,
const viz::SharedImageFormat& format,
gfx::BufferUsage buffer_usage,
gfx::GpuMemoryBufferHandle* handle);
#if BUILDFLAG(IS_WIN)
void CopyToGpuMemoryBufferAsync(
const Mailbox& mailbox,
std::vector<SyncToken> sync_token_dependencies,
uint64_t release_count,
base::OnceCallback<void(bool)> callback);
#endif
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
void CopyNativeGmbToSharedMemoryAsync(
gfx::GpuMemoryBufferHandle buffer_handle,
base::UnsafeSharedMemoryRegion memory_region,
base::OnceCallback<void(bool)> callback);
#endif
void CrashGpuProcessForTesting();
void TerminateGpuProcessForTesting();
virtual scoped_refptr<SharedImageInterface>
CreateClientSharedImageInterface();
[[nodiscard]] bool AddObserverIfNotAlreadyLost(GpuChannelLostObserver* obs);
void RemoveObserver(GpuChannelLostObserver* obs);
GpuChannelHostUtils* gpu_channel_host_utils() {
return gpu_channel_host_utils_.get();
}
protected:
friend class base::RefCountedThreadSafe<GpuChannelHost>;
virtual ~GpuChannelHost();
void ResetChannelRemoteForTesting();
private:
void EstablishSharedMemoryForFlushVerification()
EXCLUSIVE_LOCKS_REQUIRED(shared_memory_version_lock_);
struct ConnectionTracker
: public base::RefCountedThreadSafe<ConnectionTracker> {
ConnectionTracker();
bool is_connected() const { return is_connected_.load(); }
void OnDisconnectedFromGpuProcess();
[[nodiscard]] bool AddObserverIfNotAlreadyLost(GpuChannelLostObserver* obs);
void RemoveObserver(GpuChannelLostObserver* obs);
void NotifyGpuChannelLost();
private:
friend class base::RefCountedThreadSafe<ConnectionTracker>;
~ConnectionTracker();
std::atomic_bool is_connected_{true};
base::Lock channel_obs_lock_;
std::vector<GpuChannelLostObserver*> GUARDED_BY(channel_obs_lock_)
observer_list_;
};
class GPU_IPC_CLIENT_EXPORT Listener : public IPC::Listener {
public:
Listener();
~Listener() override;
void Initialize(mojo::ScopedMessagePipeHandle handle,
mojo::PendingAssociatedReceiver<mojom::GpuChannel> receiver,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
void Close();
void OnChannelError() override;
private:
mutable base::Lock lock_;
std::unique_ptr<IPC::Channel> channel_ GUARDED_BY(lock_);
};
struct OrderingBarrierInfo {
OrderingBarrierInfo();
~OrderingBarrierInfo();
OrderingBarrierInfo(OrderingBarrierInfo&&);
OrderingBarrierInfo& operator=(OrderingBarrierInfo&&);
int32_t route_id;
int32_t put_offset;
uint32_t deferred_message_id;
std::vector<SyncToken> sync_token_fences;
uint64_t release_count;
};
void EnqueuePendingOrderingBarrier();
void InternalFlush(uint32_t deferred_message_id);
const scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
const int channel_id_;
const gpu::GPUInfo gpu_info_;
const gpu::GpuFeatureInfo gpu_feature_info_;
std::unique_ptr<Listener, base::OnTaskRunnerDeleter> listener_;
const scoped_refptr<ConnectionTracker> connection_tracker_;
mojo::SharedAssociatedRemote<mojom::GpuChannel> gpu_channel_;
SharedImageInterfaceProxy shared_image_interface_;
mutable base::Lock shared_memory_version_lock_;
std::optional<mojo::SharedMemoryVersionClient> shared_memory_version_client_
GUARDED_BY(shared_memory_version_lock_);
base::MetricsSubSampler metrics_sub_sampler_;
base::AtomicSequenceNumber next_image_id_;
base::AtomicSequenceNumber next_route_id_;
mutable base::Lock deferred_message_lock_;
std::vector<mojom::DeferredRequestPtr> deferred_messages_
GUARDED_BY(deferred_message_lock_);
std::optional<OrderingBarrierInfo> pending_ordering_barrier_
GUARDED_BY(deferred_message_lock_);
uint32_t next_deferred_message_id_ GUARDED_BY(deferred_message_lock_) = 1;
uint32_t enqueued_deferred_message_id_ GUARDED_BY(deferred_message_lock_) = 0;
uint32_t flushed_deferred_message_id_ GUARDED_BY(deferred_message_lock_) = 0;
std::optional<uint32_t> delayed_flush_deferred_message_id_
GUARDED_BY(deferred_message_lock_);
static constexpr base::TimeDelta kDelayForEnsuringFlush = base::Seconds(1);
const bool sync_point_graph_validation_enabled_;
std::unique_ptr<GpuChannelHostUtils> gpu_channel_host_utils_;
};
}
#endif