// 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 MSD_IMG_CONNECTION_H
#define MSD_IMG_CONNECTION_H

#include <memory>
#include <vector>

#include "include/fuchsia_communication.h"
#include "magma_util/macros.h"
#include "msd.h"

typedef struct _PVRSRV_DEVICE_NODE_ PVRSRV_DEVICE_NODE;
typedef struct _CONNECTION_DATA_ CONNECTION_DATA;
typedef struct PVRSRV_BRIDGE_PACKAGE_TAG PVRSRV_BRIDGE_PACKAGE;

class MsdImgBuffer;
class MsdImgSemaphore;

class MsdImgConnection : public msd_connection_t
{
public:
	class Owner
	{
	public:
		virtual PVRSRV_DEVICE_NODE* device_node() = 0;
	};

	// If the current thread is currently servicing a bridge request or other
	// operation on a connection, this will return a pointer to that connection.
	static MsdImgConnection* GetCurrentConnection();

	virtual ~MsdImgConnection();

	MsdImgConnection(Owner* owner, msd_client_id_t client_id);

	void AssertValid()
	{
		// Use volatile to ensure the compiler won't optimize the check out if
		// it realizes magic_ always == kMagic outside the constructor and
		// destructor.
		DASSERT(*const_cast<volatile int32_t*>(&magic_) == kMagic);
	}

	bool Init();
	magma_status_t
	ExecuteCommandBuffer(msd_buffer_t* cmd_buf, msd_buffer_t** exec_resources, msd_semaphore_t** signal_semaphores);
	bool CopyFromUser(void* dest, const void* src, uint32_t size);
	bool CopyToUser(void* dest, const void* src, uint32_t size);


	static MsdImgConnection* Cast(msd_connection_t* msd_connection)
	{
		DASSERT(msd_connection);
		DASSERT(msd_connection->magic_ == kMagic);
		return static_cast<MsdImgConnection*>(msd_connection);
	}

	static MsdImgConnection* Cast(void* void_connection)
	{
		DASSERT(void_connection);
		auto msd_connection = static_cast<MsdImgConnection*>(void_connection);
		msd_connection->AssertValid();
		return msd_connection;
	}

	Owner* owner() const { return owner_; }
	msd_client_id_t client_id() const { return client_id_; }
	// This is unchecked and comes from the client, so it should only be used
	// for debug logging.
	uint64_t current_client_thread_id() const { return current_client_thread_id_; }

	char* client_name() { return client_name_; }

	// Takes ownership of an additional buffer that was sent along with a
	// command buffer. Once the buffer is taken, subsequent calls within the
	// same execution of a bridge command will return null.
	std::shared_ptr<MsdImgBuffer> TakeAdditionalBuffer();

	// Takes ownership of an additional semaphore that was sent along with a
	// command buffer. Once the semaphore is taken, subsequent calls within the
	// same execution of a bridge command will return null.
	std::shared_ptr<MsdImgSemaphore> TakeAdditionalSemaphore();

private:
	friend class TestMsdImgConnection;
	friend class TestOsFunc;

	magma_status_t ProcessCommandBuffer(msd_buffer_t* cmd_buf,
					    msd_buffer_t** exec_resources,
					    msd_semaphore_t** signal_semaphores,
					    PVRSRV_BRIDGE_PACKAGE* package_out,
					    volatile FuchsiaImgCommandPayload** payload_out,
					    std::vector<std::shared_ptr<MsdImgSemaphore>>* semaphores_out);
	void CleanupAfterCommand(volatile FuchsiaImgCommandPayload* payload,
				 const std::vector<std::shared_ptr<MsdImgSemaphore>>& semaphores,
				 bool success);

	static const uint32_t kMagic = 'icon';
	Owner* owner_;
	msd_client_id_t client_id_;
	CONNECTION_DATA* connection_data_ = nullptr;
	char client_name_[32];
	uint64_t current_client_thread_id_;

	// This member is only valid when ExecuteCommandBuffer is executing.
	std::shared_ptr<MsdImgBuffer> payload_buffer_;

	std::shared_ptr<MsdImgBuffer> additional_buffer_;
	std::shared_ptr<MsdImgSemaphore> additional_semaphore_;
};

#endif // MSD_IMG_CONNECTION_H
