#ifndef GPU_IPC_SERVICE_COMMAND_BUFFER_STUB_H_
#define GPU_IPC_SERVICE_COMMAND_BUFFER_STUB_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "arkweb/build/features/features.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/stack_allocated.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "gpu/command_buffer/common/command_buffer_id.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/decoder_client.h"
#include "gpu/command_buffer/service/program_cache.h"
#include "gpu/command_buffer/service/scheduler_task_runner.h"
#include "gpu/command_buffer/service/sequence_id.h"
#include "gpu/command_buffer/service/task_graph.h"
#include "gpu/ipc/common/gpu_channel.mojom.h"
#include "gpu/ipc/common/surface_handle.h"
#include "gpu/ipc/service/context_url.h"
#include "gpu/ipc/service/gpu_ipc_service_export.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/shared_associated_remote.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_memory_buffer_handle.h"
#include "ui/gfx/swap_result.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gpu_preference.h"
namespace gpu {
class DecoderContext;
class MemoryTracker;
struct SyncToken;
struct WaitForCommandState;
class GpuChannel;
class GPU_IPC_SERVICE_EXPORT CommandBufferStub
: public CommandBufferServiceClient,
public DecoderClient,
public mojom::CommandBuffer {
public:
class DestructionObserver {
public:
virtual void OnWillDestroyStub(bool have_context) = 0;
protected:
virtual ~DestructionObserver() = default;
};
CommandBufferStub(GpuChannel* channel,
const mojom::CreateCommandBufferParams& init_params,
CommandBufferId command_buffer_id,
SequenceId sequence_id,
int32_t stream_id,
int32_t route_id);
CommandBufferStub(const CommandBufferStub&) = delete;
CommandBufferStub& operator=(const CommandBufferStub&) = delete;
~CommandBufferStub() override;
scoped_refptr<base::SequencedTaskRunner> task_runner() const {
return scheduler_task_runner_;
}
virtual gpu::ContextResult Initialize(
const mojom::CreateCommandBufferParams& params,
base::UnsafeSharedMemoryRegion shared_state_shm) = 0;
void BindEndpoints(
mojo::PendingAssociatedReceiver<mojom::CommandBuffer> receiver,
mojo::PendingAssociatedRemote<mojom::CommandBufferClient> client,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
MemoryTracker* GetMemoryTracker() const;
virtual MemoryTracker* GetContextGroupMemoryTracker() const = 0;
virtual base::WeakPtr<CommandBufferStub> AsWeakPtr() = 0;
void ExecuteDeferredRequest(mojom::DeferredCommandBufferRequestParams& params,
FenceSyncReleaseDelegate* release_delegate);
using WaitForStateCallback =
base::OnceCallback<void(const gpu::CommandBuffer::State&)>;
void WaitForTokenInRange(int32_t start,
int32_t end,
WaitForStateCallback callback);
void WaitForGetOffsetInRange(uint32_t set_get_buffer_count,
int32_t start,
int32_t end,
WaitForStateCallback callback);
#if BUILDFLAG(ARKWEB_BUGFIX_CRASH)
void WaitForGetOffsetInRangeTimeout();
#endif
CommandBatchProcessedResult OnCommandBatchProcessed() override;
void OnParseError() override;
void OnConsoleMessage(int32_t id, const std::string& message) override;
void CacheBlob(gpu::GpuDiskCacheType type,
const std::string& key,
const std::string& blob) override;
void OnFenceSyncRelease(uint64_t release) override;
void OnDescheduleUntilFinished() override;
void OnRescheduleAfterFinished() override;
void ScheduleGrContextCleanup() override;
void HandleReturnData(base::span<const uint8_t> data) override;
bool ShouldYield() override;
using MemoryTrackerFactory =
base::RepeatingCallback<scoped_refptr<MemoryTracker>()>;
static void SetMemoryTrackerFactoryForTesting(MemoryTrackerFactory factory);
scoped_refptr<Buffer> GetTransferBuffer(int32_t id);
void RegisterTransferBufferForTest(int32_t id, scoped_refptr<Buffer> buffer);
bool IsScheduled();
bool HasUnprocessedCommands();
DecoderContext* decoder_context() const { return decoder_context_.get(); }
GpuChannel* channel() const { return channel_; }
CommandBufferId command_buffer_id() const { return command_buffer_id_; }
SequenceId sequence_id() const { return sequence_id_; }
int32_t stream_id() const { return stream_id_; }
gl::GLSurface* surface() const { return surface_.get(); }
bool has_stateful_context() const { return has_stateful_context_; }
void AddDestructionObserver(DestructionObserver* observer);
void RemoveDestructionObserver(DestructionObserver* observer);
void MarkContextLost();
scoped_refptr<gl::GLShareGroup> share_group() { return share_group_; }
protected:
class ScopedContextOperation {
STACK_ALLOCATED();
public:
explicit ScopedContextOperation(CommandBufferStub& stub);
~ScopedContextOperation();
bool is_context_current() const { return cache_use_.has_value(); }
private:
CommandBufferStub& stub_;
bool have_context_ = false;
std::optional<gles2::ProgramCache::ScopedCacheUse> cache_use_;
};
mojom::CommandBufferClient& client() { return *client_.get(); }
void SetGetBuffer(int32_t shm_id) override;
void RegisterTransferBuffer(
int32_t id,
base::UnsafeSharedMemoryRegion transfer_buffer) override;
void CreateGpuFenceFromHandle(uint32_t id,
gfx::GpuFenceHandle handle) override;
void GetGpuFenceHandle(uint32_t id,
GetGpuFenceHandleCallback callback) override;
void SignalSyncToken(const SyncToken& sync_token, uint32_t id) override;
void SignalQuery(uint32_t query, uint32_t id) override;
scoped_refptr<MemoryTracker> CreateMemoryTracker() const;
void set_decoder_context(std::unique_ptr<DecoderContext> decoder_context) {
decoder_context_ = std::move(decoder_context);
}
void CheckContextLost();
void UpdateActiveUrl();
bool MakeCurrent();
const raw_ptr<GpuChannel> channel_;
ContextUrl active_url_;
std::string context_label_;
bool initialized_;
bool use_virtualized_gl_context_;
std::unique_ptr<CommandBufferService> command_buffer_;
scoped_refptr<MemoryTracker> memory_tracker_;
scoped_refptr<gl::GLSurface> surface_;
ScopedSyncPointClientState scoped_sync_point_client_state_;
scoped_refptr<gl::GLShareGroup> share_group_;
const CommandBufferId command_buffer_id_;
const SequenceId sequence_id_;
const scoped_refptr<SchedulerTaskRunner> scheduler_task_runner_;
const int32_t stream_id_;
const int32_t route_id_;
private:
void Destroy();
void CreateCacheUse(
std::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use);
void OnAsyncFlush(int32_t put_offset,
uint32_t flush_id,
const std::vector<SyncToken>& sync_token_fences);
void OnDestroyTransferBuffer(int32_t id);
void OnSignalAck(uint32_t id);
void ReportState();
void PollWork();
void PerformWork();
void ScheduleDelayedWork(base::TimeDelta delay);
void CheckCompleteWaits();
static void SetContextGpuFeatureInfo(gl::GLContext* context,
const GpuFeatureInfo& gpu_feature_info);
static MemoryTrackerFactory GetMemoryTrackerFactory();
static MemoryTrackerFactory SetOrGetMemoryTrackerFactory(
MemoryTrackerFactory factory);
std::unique_ptr<DecoderContext> decoder_context_;
uint32_t last_flush_id_;
base::ObserverList<DestructionObserver>::Unchecked destruction_observers_;
base::DeadlineTimer process_delayed_work_timer_;
uint32_t previous_processed_num_;
base::TimeTicks last_idle_time_;
std::unique_ptr<WaitForCommandState> wait_for_token_;
std::unique_ptr<WaitForCommandState> wait_for_get_offset_;
uint32_t wait_set_get_buffer_count_;
mojo::AssociatedReceiver<mojom::CommandBuffer> receiver_{this};
mojo::SharedAssociatedRemote<mojom::CommandBufferClient> client_;
const bool has_stateful_context_;
raw_ptr<FenceSyncReleaseDelegate> release_delegate_ = nullptr;
};
}
#endif