1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <semaphore.h>
8 #include <stdlib.h>
9 
10 #include <ddk/protocol/display/controller.h>
11 #include <fbl/unique_ptr.h>
12 #include <zircon/pixelformat.h>
13 #include <zircon/compiler.h>
14 
15 #include "device.h"
16 #include "ring.h"
17 #include "virtio_gpu.h"
18 
19 namespace virtio {
20 
21 class Ring;
22 
23 class GpuDevice : public Device {
24 public:
25     GpuDevice(zx_device_t* device, zx::bti bti, fbl::unique_ptr<Backend> backend);
26     virtual ~GpuDevice();
27 
28     zx_status_t Init() override;
29 
30     void IrqRingUpdate() override;
31     void IrqConfigChange() override;
32 
pmode()33     const virtio_gpu_resp_display_info::virtio_gpu_display_one* pmode() const { return &pmode_; }
34 
35     void Flush();
36 
tag()37     const char* tag() const override { return "virtio-gpu"; };
38 
39 private:
40     // DDK driver hooks
41     static void virtio_gpu_set_display_controller_interface(
42             void* ctx, const display_controller_interface_t* intf);
43     static zx_status_t virtio_gpu_import_vmo_image(
44             void* ctx, image_t* image, zx_handle_t vmo, size_t offset);
45     static void virtio_gpu_release_image(void* ctx, image_t* image);
46     static uint32_t virtio_gpu_check_configuration(
47         void* ctx, const display_config_t** display_configs, size_t display_count,
48         uint32_t** layer_cfg_results, size_t* layer_cfg_result_count);
49     static void virtio_gpu_apply_configuration(
50             void* ctx, const display_config_t** display_configs, size_t display_count);
51     static uint32_t virtio_gpu_compute_linear_stride(
52             void* ctx, uint32_t width, zx_pixel_format_t format);
53     static zx_status_t virtio_gpu_allocate_vmo(void* ctx, uint64_t size, zx_handle_t* vmo_out);
54 
55 
56     // Internal routines
57     template <typename RequestType, typename ResponseType>
58     void send_command_response(const RequestType* cmd, ResponseType** res);
59 
60     zx_status_t get_display_info();
61     zx_status_t allocate_2d_resource(uint32_t* resource_id, uint32_t width, uint32_t height);
62     zx_status_t attach_backing(uint32_t resource_id, zx_paddr_t ptr, size_t buf_len);
63     zx_status_t set_scanout(uint32_t scanout_id, uint32_t resource_id, uint32_t width, uint32_t height);
64     zx_status_t flush_resource(uint32_t resource_id, uint32_t width, uint32_t height);
65     zx_status_t transfer_to_host_2d(uint32_t resource_id, uint32_t width, uint32_t height);
66 
67     zx_status_t virtio_gpu_start();
68     thrd_t start_thread_ = {};
69 
70     // the main virtio ring
71     Ring vring_ = {this};
72 
73     // display protocol ops
74     display_controller_impl_protocol_ops_t display_proto_ops_ = {};
75 
76     // gpu op
77     io_buffer_t gpu_req_;
78 
79     // A saved copy of the display
80     virtio_gpu_resp_display_info::virtio_gpu_display_one pmode_ = {};
81     int pmode_id_ = -1;
82 
83     uint32_t next_resource_id_ = 1;
84 
85     fbl::Mutex request_lock_;
86     sem_t request_sem_;
87     sem_t response_sem_;
88 
89     // Flush thread
90     void virtio_gpu_flusher();
91     thrd_t flush_thread_ = {};
92     fbl::Mutex flush_lock_;
93     cnd_t flush_cond_ = {};
94     bool flush_pending_ = false;
95 
96     display_controller_interface_t dc_intf_;
97 
98     struct imported_image* current_fb_;
99     struct imported_image* displayed_fb_;
100 
101     zx_pixel_format_t supported_formats_ = ZX_PIXEL_FORMAT_RGB_x888;
102 };
103 
104 } // namespace virtio
105