blob: d9205ee698e38d77b4a75324660cc8359f189fb4 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 SRC_GRAPHICS_DRIVERS_MISC_GOLDFISH_CONTROL_CONTROL_DEVICE_H_
#define SRC_GRAPHICS_DRIVERS_MISC_GOLDFISH_CONTROL_CONTROL_DEVICE_H_
#include <fidl/fuchsia.hardware.goldfish.pipe/cpp/wire.h>
#include <fidl/fuchsia.hardware.goldfish/cpp/markers.h>
#include <fidl/fuchsia.hardware.goldfish/cpp/wire.h>
#include <fidl/fuchsia.sysmem2/cpp/fidl.h>
#include <lib/component/outgoing/cpp/outgoing_directory.h>
#include <lib/ddk/device.h>
#include <lib/ddk/io-buffer.h>
#include <lib/fpromise/result.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <zircon/types.h>
#include <map>
#include <vector>
#include <ddktl/device.h>
#include <fbl/condition_variable.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/mutex.h>
#include "src/graphics/drivers/misc/goldfish_control/heap.h"
namespace goldfish {
class Control;
using ControlType =
ddk::Device<Control, ddk::Messageable<fuchsia_hardware_goldfish::ControlDevice>::Mixin>;
class Control : public ControlType {
public:
static zx_status_t Create(void* ctx, zx_device_t* parent);
explicit Control(zx_device_t* parent, async_dispatcher_t* dispatcher);
~Control();
zx_status_t Bind();
void RegisterBufferHandle(BufferKey buffer_key);
void FreeBufferHandle(BufferKey buffer_key);
using CreateColorBuffer2Result = fpromise::result<
fidl::WireResponse<fuchsia_hardware_goldfish::ControlDevice::CreateColorBuffer2>,
zx_status_t>;
CreateColorBuffer2Result CreateColorBuffer2(
const zx::vmo& vmo, BufferKey buffer_key,
fuchsia_hardware_goldfish::wire::CreateColorBuffer2Params create_params);
// |fidl::WireServer<fuchsia_hardware_goldfish::ControlDevice>|
void CreateColorBuffer2(CreateColorBuffer2RequestView request,
CreateColorBuffer2Completer::Sync& completer) override;
using CreateBuffer2Result =
fpromise::result<fuchsia_hardware_goldfish::wire::ControlDeviceCreateBuffer2Result,
zx_status_t>;
CreateBuffer2Result CreateBuffer2(
fidl::AnyArena& allocator, const zx::vmo& vmo, BufferKey buffer_key,
fuchsia_hardware_goldfish::wire::CreateBuffer2Params create_params);
// |fidl::WireServer<fuchsia_hardware_goldfish::ControlDevice>|
void CreateBuffer2(CreateBuffer2RequestView request,
CreateBuffer2Completer::Sync& completer) override;
// |fidl::WireServer<fuchsia_hardware_goldfish::ControlDevice>|
void CreateSyncFence(CreateSyncFenceRequestView request,
CreateSyncFenceCompleter::Sync& completer) override;
// |fidl::WireServer<fuchsia_hardware_goldfish::ControlDevice>|
void GetBufferHandle(GetBufferHandleRequestView request,
GetBufferHandleCompleter::Sync& completer) override;
// |fidl::WireServer<fuchsia_hardware_goldfish::ControlDevice>|
void GetBufferHandleInfo(GetBufferHandleInfoRequestView request,
GetBufferHandleInfoCompleter::Sync& completer) override;
// Device protocol implementation.
void DdkRelease();
// Used by heaps. Removes a specific heap from the linked list.
void RemoveHeap(Heap* heap);
fidl::WireSyncClient<fuchsia_hardware_goldfish::AddressSpaceChildDriver>& address_space_child() {
return address_space_child_;
}
private:
zx_status_t Init();
zx_status_t InitAddressSpaceDeviceLocked() TA_REQ(lock_);
zx_status_t InitPipeDeviceLocked() TA_REQ(lock_);
zx_status_t InitSyncDeviceLocked() TA_REQ(lock_);
// TODO(https://fxbug.dev/42161642): Remove these pipe IO functions and use
// //src/devices/lib/goldfish/pipe_io instead.
int32_t WriteLocked(uint32_t cmd_size, int32_t* consumed_size) TA_REQ(lock_);
void WriteLocked(uint32_t cmd_size) TA_REQ(lock_);
zx_status_t ReadResultLocked(void* result, size_t size) TA_REQ(lock_);
zx_status_t ReadResultLocked(uint32_t* result) TA_REQ(lock_) {
return ReadResultLocked(result, sizeof(uint32_t));
}
zx_status_t ExecuteCommandLocked(uint32_t cmd_size, uint32_t* result) TA_REQ(lock_);
zx_status_t CreateBuffer2Locked(uint64_t size, uint32_t memory_property, uint32_t* id)
TA_REQ(lock_);
zx_status_t CreateColorBufferLocked(uint32_t width, uint32_t height, uint32_t format,
uint32_t* id) TA_REQ(lock_);
void CloseBufferOrColorBufferLocked(uint32_t id) TA_REQ(lock_);
void CloseBufferLocked(uint32_t id) TA_REQ(lock_);
void CloseColorBufferLocked(uint32_t id) TA_REQ(lock_);
zx_status_t SetColorBufferVulkanModeLocked(uint32_t id, uint32_t mode, uint32_t* result)
TA_REQ(lock_);
zx_status_t SetColorBufferVulkanMode2Locked(uint32_t id, uint32_t mode, uint32_t memory_property,
uint32_t* result) TA_REQ(lock_);
zx_status_t MapGpaToBufferHandleLocked(uint32_t id, uint64_t gpa, uint64_t size, uint32_t* result)
TA_REQ(lock_);
zx_status_t CreateSyncKHRLocked(uint64_t* glsync_out, uint64_t* syncthread_out) TA_REQ(lock_);
fit::result<zx_status_t, BufferKey> GetBufferKeyForVmo(const zx::vmo& vmo);
fuchsia_hardware_goldfish_pipe::Service::InstanceHandler
CreateGoldfishPipeServiceInstanceHandler();
fuchsia_hardware_sysmem::Service::InstanceHandler CreateSysmemServiceInstanceHandler();
fbl::Mutex lock_;
fidl::WireSyncClient<fuchsia_hardware_goldfish_pipe::GoldfishPipe> pipe_;
fidl::WireSyncClient<fuchsia_hardware_goldfish::AddressSpaceDevice> address_space_;
fidl::WireSyncClient<fuchsia_hardware_goldfish::SyncDevice> sync_;
fidl::SyncClient<fuchsia_sysmem2::Allocator> sysmem_;
int32_t id_ = 0;
zx::bti bti_ TA_GUARDED(lock_);
ddk::IoBuffer cmd_buffer_ TA_GUARDED(lock_);
ddk::IoBuffer io_buffer_ TA_GUARDED(lock_);
fbl::DoublyLinkedList<std::unique_ptr<Heap>> heaps_ TA_GUARDED(lock_);
std::vector<std::unique_ptr<Heap>> removed_heaps_;
zx::event pipe_event_;
fidl::WireSyncClient<fuchsia_hardware_goldfish::AddressSpaceChildDriver> address_space_child_;
fidl::WireSyncClient<fuchsia_hardware_goldfish::SyncTimeline> sync_timeline_;
// TODO(https://fxbug.dev/42107181): This should be std::unordered_map.
//
// buffer_collection_id, buffer_index
std::map<BufferKey, uint32_t> buffer_handles_ TA_GUARDED(lock_);
struct BufferHandleInfo {
fuchsia_hardware_goldfish::wire::BufferHandleType type;
uint32_t memory_property;
};
std::map<uint32_t, BufferHandleInfo> buffer_handle_info_ TA_GUARDED(lock_);
// The outgoing services are dispatched onto `dispatcher_`.
async_dispatcher_t* dispatcher_;
component::OutgoingDirectory outgoing_;
fidl::ServerBindingGroup<fuchsia_hardware_goldfish::ControlDevice> bindings_;
DISALLOW_COPY_ASSIGN_AND_MOVE(Control);
};
} // namespace goldfish
#endif // SRC_GRAPHICS_DRIVERS_MISC_GOLDFISH_CONTROL_CONTROL_DEVICE_H_