blob: 011953cdbf5cafef5eb4d0dd036540e3d4b61b5c [file] [log] [blame]
// Copyright 2017 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 GARNET_LIB_MACHINA_VIRTIO_GPU_H_
#define GARNET_LIB_MACHINA_VIRTIO_GPU_H_
#include <fbl/intrusive_hash_table.h>
#include <fbl/unique_ptr.h>
#include <virtio/gpu.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
#include "garnet/lib/machina/virtio.h"
#define VIRTIO_GPU_Q_CONTROLQ 0
#define VIRTIO_GPU_Q_CURSORQ 1
#define VIRTIO_GPU_Q_COUNT 2
namespace machina {
class GpuResource;
class GpuScanout;
class VirtioGpu;
using ResourceId = uint32_t;
using ScanoutId = uint32_t;
// Virtio 2D GPU device.
class VirtioGpu : public VirtioDevice {
public:
VirtioGpu(const PhysMem& phys_mem);
~VirtioGpu() override;
virtio_queue_t& control_queue() { return queues_[VIRTIO_GPU_Q_CONTROLQ]; }
virtio_queue_t& cursor_queue() { return queues_[VIRTIO_GPU_Q_CURSORQ]; }
// Begins processing any descriptors that become available in the queues.
zx_status_t Init();
// Adds a scanout to the GPU.
//
// Currently only a single scanout is supported. ZX_ERR_ALREADY_EXISTS will
// be returned if this method is called multiple times.
zx_status_t AddScanout(GpuScanout* scanout);
zx_status_t HandleGpuCommand(virtio_queue_t* queue,
uint16_t head,
uint32_t* used);
protected:
static zx_status_t QueueHandler(virtio_queue_t* queue,
uint16_t head,
uint32_t* used,
void* ctx);
// VIRTIO_GPU_CMD_GET_DISPLAY_INFO
void GetDisplayInfo(const virtio_gpu_ctrl_hdr_t* request,
virtio_gpu_resp_display_info_t* response);
// VIRTIO_GPU_CMD_RESOURCE_CREATE_2D
void ResourceCreate2D(const virtio_gpu_resource_create_2d_t* request,
virtio_gpu_ctrl_hdr_t* response);
// VIRTIO_GPU_CMD_RESOURCE_UNREF
void ResourceUnref(const virtio_gpu_resource_unref_t* request,
virtio_gpu_ctrl_hdr_t* response);
// VIRTIO_GPU_CMD_SET_SCANOUT
void SetScanout(const virtio_gpu_set_scanout_t* request,
virtio_gpu_ctrl_hdr_t* response);
// VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING
void ResourceAttachBacking(
const virtio_gpu_resource_attach_backing_t* request,
const virtio_gpu_mem_entry_t* mem_entries,
virtio_gpu_ctrl_hdr_t* response);
// VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING
void ResourceDetachBacking(
const virtio_gpu_resource_detach_backing_t* request,
virtio_gpu_ctrl_hdr_t* response);
// VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D
void TransferToHost2D(const virtio_gpu_transfer_to_host_2d_t* request,
virtio_gpu_ctrl_hdr_t* response);
// VIRTIO_GPU_CMD_RESOURCE_FLUSH
void ResourceFlush(const virtio_gpu_resource_flush_t* request,
virtio_gpu_ctrl_hdr_t* response);
private:
GpuScanout* scanout_ = nullptr;
// Fix the number of hash table buckets to 1 because linux and zircon
// virtcons only use a single resource.
static constexpr size_t kNumHashTableBuckets = 1;
using ResourceTable =
fbl::HashTable<ResourceId,
fbl::unique_ptr<GpuResource>,
fbl::SinglyLinkedList<fbl::unique_ptr<GpuResource>>,
size_t,
kNumHashTableBuckets>;
ResourceTable resources_;
virtio_queue_t queues_[VIRTIO_GPU_Q_COUNT];
virtio_gpu_config_t config_ = {};
};
} // namespace machina
#endif // GARNET_LIB_MACHINA_VIRTIO_GPU_H_