#ifndef GPU_IPC_IN_PROCESS_COMMAND_BUFFER_H_
#define GPU_IPC_IN_PROCESS_COMMAND_BUFFER_H_
#include <stddef.h>
#include <stdint.h>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "gpu/command_buffer/client/gpu_control.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/common/context_result.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/command_buffer_task_executor.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/decoder_client.h"
#include "gpu/command_buffer/service/decoder_context.h"
#include "gpu/command_buffer/service/display_compositor_memory_and_task_controller_on_gpu.h"
#include "gpu/command_buffer/service/gpu_task_scheduler_helper.h"
#include "gpu/command_buffer/service/gr_cache_controller.h"
#include "gpu/command_buffer/service/program_cache.h"
#include "gpu/command_buffer/service/service_transfer_cache.h"
#include "gpu/command_buffer/service/shared_image_interface_in_process.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_preferences.h"
#include "gpu/ipc/common/gpu_channel.mojom.h"
#include "gpu/ipc/common/surface_handle.h"
#include "gpu/ipc/gl_in_process_context_export.h"
#include "gpu/ipc/service/context_url.h"
#include "ui/gfx/gpu_memory_buffer_handle.h"
#include "ui/gfx/native_ui_types.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gpu_preference.h"
namespace gl {
class GLContext;
class GLShareGroup;
}
namespace gfx {
struct GpuFenceHandle;
}
namespace gpu {
class SharedContextState;
class GpuProcessShmCount;
class GpuTaskSchedulerHelper;
class FenceSyncReleaseDelegate;
class SharedImageInterface;
namespace webgpu {
class WebGPUDecoder;
}
namespace raster {
class GrShaderCache;
}
class GL_IN_PROCESS_CONTEXT_EXPORT InProcessCommandBuffer
: public CommandBuffer,
public GpuControl,
public CommandBufferServiceClient,
public DecoderClient {
public:
InProcessCommandBuffer(CommandBufferTaskExecutor* task_executor,
const GURL& active_url);
InProcessCommandBuffer(const InProcessCommandBuffer&) = delete;
InProcessCommandBuffer& operator=(const InProcessCommandBuffer&) = delete;
~InProcessCommandBuffer() override;
gpu::ContextResult Initialize(
mojom::ContextCreationAttribsPtr attribs,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
gpu::raster::GrShaderCache* gr_shader_cache,
GpuProcessShmCount* use_shader_cache_shm_count);
State GetLastState() override;
void Flush(int32_t put_offset) override;
void OrderingBarrier(int32_t put_offset) override;
State WaitForTokenInRange(int32_t start, int32_t end) override;
State WaitForGetOffsetInRange(uint32_t set_get_buffer_count,
int32_t start,
int32_t end) override;
void SetGetBuffer(int32_t shm_id) override;
scoped_refptr<Buffer> CreateTransferBuffer(
uint32_t size,
int32_t* id,
uint32_t alignment = 0,
TransferBufferAllocationOption option =
TransferBufferAllocationOption::kLoseContextOnOOM) override;
void DestroyTransferBuffer(int32_t id) override;
void ForceLostContext(error::ContextLostReason reason) override;
void SetGpuControlClient(GpuControlClient*) override;
const Capabilities& GetCapabilities() const override;
const GLCapabilities& GetGLCapabilities() const override;
void SignalQuery(uint32_t query_id, base::OnceClosure callback) override;
void CancelAllQueries() override;
void CreateGpuFence(uint32_t gpu_fence_id, ClientGpuFence source) override;
void GetGpuFence(uint32_t gpu_fence_id,
base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)>
callback) override;
void SetLock(base::Lock*) override;
void EnsureWorkVisible() override;
CommandBufferNamespace GetNamespaceID() const override;
CommandBufferId GetCommandBufferID() const override;
void FlushPendingWork() override;
uint64_t GenerateFenceSyncRelease() override;
bool IsFenceSyncReleased(uint64_t release) override;
void SignalSyncToken(const SyncToken& sync_token,
base::OnceClosure callback) override;
void WaitSyncToken(const SyncToken& sync_token) override;
bool CanWaitUnverifiedSyncToken(const SyncToken& sync_token) override;
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& shader) 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;
const gles2::FeatureInfo* GetFeatureInfo() const;
const GpuFeatureInfo& GetGpuFeatureInfo() const;
gpu::ServiceTransferCache* GetTransferCacheForTest() const;
int GetRasterDecoderIdForTest() const;
webgpu::WebGPUDecoder* GetWebGPUDecoderForTest() const;
CommandBufferTaskExecutor* service_for_testing() const {
return task_executor_;
}
gpu::SharedImageInterface* GetSharedImageInterface() const;
private:
struct InitializeOnGpuThreadParams {
mojom::ContextCreationAttribsPtr attribs;
raw_ptr<Capabilities> capabilities;
raw_ptr<GLCapabilities> gl_capabilities;
raw_ptr<gpu::raster::GrShaderCache> gr_shader_cache;
raw_ptr<GpuProcessShmCount> use_shader_cache_shm_count;
InitializeOnGpuThreadParams(mojom::ContextCreationAttribsPtr attribs,
Capabilities* capabilities,
GLCapabilities* gl_capabilities,
gpu::raster::GrShaderCache* gr_shader_cache,
GpuProcessShmCount* use_shader_cache_shm_count);
~InitializeOnGpuThreadParams();
InitializeOnGpuThreadParams(InitializeOnGpuThreadParams&& other);
InitializeOnGpuThreadParams& operator=(InitializeOnGpuThreadParams&& other);
};
gpu::ContextResult InitializeOnGpuThread(
const InitializeOnGpuThreadParams& params);
void Destroy();
bool DestroyOnGpuThread();
void FlushOnGpuThread(int32_t put_offset,
FenceSyncReleaseDelegate* release_delegate);
bool HasUnprocessedCommandsOnGpuThread();
void UpdateLastStateOnGpuThread();
void ScheduleDelayedWorkOnGpuThread();
bool MakeCurrent();
void CreateCacheUse(
std::optional<gles2::ProgramCache::ScopedCacheUse>& cache_use);
void PostOrRunClientCallback(base::OnceClosure callback);
base::OnceClosure WrapClientCallback(base::OnceClosure callback);
void RunTaskCallbackOnGpuThread(TaskCallback task,
FenceSyncReleaseDelegate* release_delegate);
void RunTaskClosureOnGpuThread(base::OnceClosure task);
void ScheduleGpuTask(
TaskCallback task,
std::vector<SyncToken> sync_token_fences = std::vector<SyncToken>(),
const SyncToken& release = SyncToken());
void ScheduleGpuTask(
base::OnceClosure task,
std::vector<SyncToken> sync_token_fences = std::vector<SyncToken>(),
const SyncToken& release = SyncToken());
void ContinueGpuTask(TaskCallback task);
void SignalQueryOnGpuThread(unsigned query_id, base::OnceClosure callback);
void CancelAllQueriesOnGpuThread();
void RegisterTransferBufferOnGpuThread(int32_t id,
scoped_refptr<Buffer> buffer);
void DestroyTransferBufferOnGpuThread(int32_t id);
void ForceLostContextOnGpuThread(error::ContextLostReason reason);
void SetGetBufferOnGpuThread(int32_t shm_id, base::WaitableEvent* completion);
void CreateGpuFenceOnGpuThread(uint32_t gpu_fence_id,
gfx::GpuFenceHandle handle);
void GetGpuFenceOnGpuThread(
uint32_t gpu_fence_id,
base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback);
void UpdateActiveUrl();
void PerformDelayedWorkOnGpuThread();
void OnContextLost();
void HandleReturnDataOnOriginThread(std::vector<uint8_t> data);
const CommandBufferId command_buffer_id_;
const ContextUrl active_url_;
bool use_virtualized_gl_context_ = false;
raw_ptr<raster::GrShaderCache> gr_shader_cache_ = nullptr;
scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
std::unique_ptr<CommandBufferService> command_buffer_;
std::unique_ptr<DecoderContext> decoder_;
scoped_refptr<gl::GLContext> context_;
ScopedSyncPointClientState sync_point_client_state_;
raw_ptr<FenceSyncReleaseDelegate> release_delegate_ = nullptr;
bool delayed_work_pending_ = false;
SEQUENCE_CHECKER(gpu_sequence_checker_);
raw_ptr<GpuControlClient> gpu_control_client_ = nullptr;
#if DCHECK_IS_ON()
bool context_lost_ = false;
#endif
State last_state_;
base::Lock last_state_lock_;
int32_t last_put_offset_ = -1;
Capabilities capabilities_;
GLCapabilities gl_capabilities_;
uint64_t next_fence_sync_release_ = 1;
std::vector<SyncToken> next_flush_sync_token_fences_;
SEQUENCE_CHECKER(client_sequence_checker_);
base::WaitableEvent flush_event_;
const raw_ptr<CommandBufferTaskExecutor> task_executor_;
std::unique_ptr<GpuTaskSchedulerHelper> task_scheduler_holder_;
raw_ptr<SingleTaskSequence> task_sequence_;
scoped_refptr<SharedImageInterfaceInProcess> shared_image_interface_;
scoped_refptr<gles2::ContextGroup> context_group_;
scoped_refptr<gl::GLShareGroup> gl_share_group_;
base::WaitableEvent fence_sync_wait_event_;
scoped_refptr<SharedContextState> context_state_;
base::WeakPtr<InProcessCommandBuffer> client_thread_weak_ptr_;
base::WeakPtrFactory<InProcessCommandBuffer> client_thread_weak_ptr_factory_{
this};
base::WeakPtrFactory<InProcessCommandBuffer> gpu_thread_weak_ptr_factory_{
this};
};
}
#endif