#pragma once

#include <util/types.hpp>
#include "Utilities/address_range.h"

#include "glutils/buffer_object.h"

// TODO: Unify the DMA implementation across backends as part of RSX restructuring.
namespace gl
{
	using dma_mapping_handle = std::pair<u32, gl::buffer*>;

	dma_mapping_handle map_dma(u32 guest_addr, u32 length);
	void clear_dma_resources();

	// GL does not currently support mixed block types...
	class dma_block
	{
	public:
		dma_block() = default;

		void allocate(u32 base_address, u32 block_size);
		void resize(u32 new_length);
		void* map(const utils::address_range& range) const;

		void set_parent(const dma_block* other);
		const dma_block* head() const
		{
			return m_parent ? m_parent : this;
		}
		bool can_map(const utils::address_range& range) const;

		u32 base_addr() const
		{
			return m_base_address;
		}
		u32 length() const
		{
			return m_data ? static_cast<u32>(m_data->size()) : 0;
		}
		bool empty() const
		{
			return length() == 0;
		}
		buffer* get() const
		{
			return m_data.get();
		}
		utils::address_range range() const
		{
			return utils::address_range::start_length(m_base_address, length());
		}

	protected:
		u32 m_base_address = 0;
		const dma_block* m_parent = nullptr;
		std::unique_ptr<gl::buffer> m_data;
	};
} // namespace gl
