blob: 6f93a37e9eff26dfee5b533f15ad81b205e765f1 [file] [log] [blame]
// Copyright 2016 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_INTEL_CONTEXT_H
#define MSD_INTEL_CONTEXT_H
#include "command_buffer.h"
#include "magma_util/semaphore_port.h"
#include "magma_util/status.h"
#include "msd.h"
#include "msd_intel_buffer.h"
#include "ppgtt.h"
#include "ringbuffer.h"
#include "types.h"
#include <map>
#include <memory>
#include <queue>
#include <thread>
class MsdIntelConnection;
// Abstract base context.
class MsdIntelContext {
public:
MsdIntelContext(std::shared_ptr<AddressSpace> address_space) : address_space_(address_space)
{
DASSERT(address_space_);
}
virtual ~MsdIntelContext() {}
void SetEngineState(EngineCommandStreamerId id, std::unique_ptr<MsdIntelBuffer> context_buffer,
std::unique_ptr<Ringbuffer> ringbuffer);
virtual bool Map(std::shared_ptr<AddressSpace> address_space, EngineCommandStreamerId id);
virtual bool Unmap(EngineCommandStreamerId id);
virtual std::weak_ptr<MsdIntelConnection> connection()
{
return std::weak_ptr<MsdIntelConnection>();
}
virtual bool killed() { return false; }
virtual void Kill() { magma::log(magma::LOG_WARNING, "Attemping to kill the global context"); }
// Gets the gpu address of the context buffer if mapped.
bool GetGpuAddress(EngineCommandStreamerId id, gpu_addr_t* addr_out);
bool GetRingbufferGpuAddress(EngineCommandStreamerId id, gpu_addr_t* addr_out);
MsdIntelBuffer* get_context_buffer(EngineCommandStreamerId id)
{
auto iter = state_map_.find(id);
return iter == state_map_.end() ? nullptr : iter->second.context_buffer.get();
}
void* GetCachedContextBufferCpuAddr(EngineCommandStreamerId id)
{
auto iter = state_map_.find(id);
if (iter == state_map_.end())
return nullptr;
if (!iter->second.context_buffer_cpu_addr) {
MsdIntelBuffer* context_buffer = iter->second.context_buffer.get();
if (!context_buffer)
return nullptr;
if (!context_buffer->platform_buffer()->MapCpu(&iter->second.context_buffer_cpu_addr))
return DRETP(nullptr, "Failed to map context buffer");
}
return iter->second.context_buffer_cpu_addr;
}
Ringbuffer* get_ringbuffer(EngineCommandStreamerId id)
{
auto iter = state_map_.find(id);
return iter == state_map_.end() ? nullptr : iter->second.ringbuffer.get();
}
bool IsInitializedForEngine(EngineCommandStreamerId id)
{
return state_map_.find(id) != state_map_.end();
}
std::queue<std::unique_ptr<MappedBatch>>& pending_batch_queue() { return pending_batch_queue_; }
std::shared_ptr<AddressSpace> exec_address_space() { return address_space_; }
private:
struct PerEngineState {
std::shared_ptr<MsdIntelBuffer> context_buffer;
std::unique_ptr<GpuMapping> context_mapping;
std::unique_ptr<Ringbuffer> ringbuffer;
void* context_buffer_cpu_addr = nullptr;
};
std::map<EngineCommandStreamerId, PerEngineState> state_map_;
std::queue<std::unique_ptr<MappedBatch>> pending_batch_queue_;
std::shared_ptr<AddressSpace> address_space_;
friend class TestContext;
};
class ClientContext : public MsdIntelContext {
public:
ClientContext(std::weak_ptr<MsdIntelConnection> connection,
std::shared_ptr<AddressSpace> address_space)
: MsdIntelContext(std::move(address_space)), connection_(connection)
{
}
~ClientContext();
magma::Status SubmitCommandBuffer(std::unique_ptr<CommandBuffer> cmd_buf);
void Shutdown();
std::weak_ptr<MsdIntelConnection> connection() override { return connection_; }
bool killed() override { return killed_; }
void Kill() override;
private:
magma::Status SubmitPendingCommandBuffer(bool have_lock);
std::weak_ptr<MsdIntelConnection> connection_;
std::unique_ptr<magma::SemaphorePort> semaphore_port_;
std::thread wait_thread_;
std::mutex pending_command_buffer_mutex_;
std::queue<std::unique_ptr<CommandBuffer>> pending_command_buffer_queue_;
bool killed_ = false;
};
class MsdIntelAbiContext : public msd_context_t {
public:
MsdIntelAbiContext(std::shared_ptr<ClientContext> ptr) : ptr_(std::move(ptr))
{
magic_ = kMagic;
}
static MsdIntelAbiContext* cast(msd_context_t* context)
{
DASSERT(context);
DASSERT(context->magic_ == kMagic);
return static_cast<MsdIntelAbiContext*>(context);
}
std::shared_ptr<ClientContext> ptr() { return ptr_; }
private:
std::shared_ptr<ClientContext> ptr_;
static const uint32_t kMagic = 0x63747874; // "ctxt"
};
#endif // MSD_INTEL_CONTEXT_H