xref: /aosp_15_r20/external/virglrenderer/src/drm/drm_renderer.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1 /*
2  * Copyright 2022 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "config.h"
7 
8 #include <errno.h>
9 #include <inttypes.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <unistd.h>
13 
14 #include <xf86drm.h>
15 
16 #include "drm_hw.h"
17 #include "drm_renderer.h"
18 
19 #ifdef ENABLE_DRM_MSM
20 #  include "msm/msm_renderer.h"
21 #endif
22 
23 static struct virgl_renderer_capset_drm capset;
24 
25 static const struct backend {
26    uint32_t context_type;
27    const char *name;
28    int (*probe)(int fd, struct virgl_renderer_capset_drm *capset);
29    struct virgl_context *(*create)(int fd);
30 } backends[] = {
31 #ifdef ENABLE_DRM_MSM
32    {
33       .context_type = VIRTGPU_DRM_CONTEXT_MSM,
34       .name = "msm",
35       .probe = msm_renderer_probe,
36       .create = msm_renderer_create,
37    },
38 #endif
39 };
40 
41 int
drm_renderer_init(int drm_fd)42 drm_renderer_init(int drm_fd)
43 {
44    for (unsigned i = 0; i < ARRAY_SIZE(backends); i++) {
45       const struct backend *b = &backends[i];
46       int fd;
47 
48       if (drm_fd != -1) {
49          fd = drm_fd;
50       } else {
51          fd = drmOpenWithType(b->name, NULL, DRM_NODE_RENDER);
52          if (fd < 0)
53             continue;
54       }
55 
56       drmVersionPtr ver = drmGetVersion(fd);
57       if (!ver) {
58          close(fd);
59          return -ENOMEM;
60       }
61 
62       if (strcmp(ver->name, b->name)) {
63          /* In the drmOpenWithType() path, we will only get back an fd
64           * for the device with matching name.  But when we are using
65           * an externally provided fd, we need to go thru the backends
66           * table to see which one has the matching name.
67           */
68          assert(drm_fd != -1);
69          drmFreeVersion(ver);
70          continue;
71       }
72 
73       capset.version_major = ver->version_major;
74       capset.version_minor = ver->version_minor;
75       capset.version_patchlevel = ver->version_patchlevel;
76       capset.context_type = b->context_type;
77 
78       int ret = b->probe(fd, &capset);
79       if (ret)
80          memset(&capset, 0, sizeof(capset));
81 
82       drmFreeVersion(ver);
83       close(fd);
84       return ret;
85    }
86 
87    if (drm_fd != -1)
88       close(drm_fd);
89 
90    return -ENODEV;
91 }
92 
93 void
drm_renderer_fini(void)94 drm_renderer_fini(void)
95 {
96    drm_log("");
97 }
98 
99 void
drm_renderer_reset(void)100 drm_renderer_reset(void)
101 {
102    drm_log("");
103 }
104 
105 size_t
drm_renderer_capset(void * _c)106 drm_renderer_capset(void *_c)
107 {
108    struct virgl_renderer_capset_drm *c = _c;
109    drm_log("c=%p", c);
110 
111    if (!capset.context_type)
112       return 0;
113 
114    if (c)
115       *c = capset;
116 
117    return sizeof(*c);
118 }
119 
120 struct virgl_context *
drm_renderer_create(UNUSED size_t debug_len,UNUSED const char * debug_name)121 drm_renderer_create(UNUSED size_t debug_len, UNUSED const char *debug_name)
122 {
123    for (unsigned i = 0; i < ARRAY_SIZE(backends); i++) {
124       const struct backend *b = &backends[i];
125 
126       if (b->context_type != capset.context_type)
127          continue;
128 
129       int fd = drmOpenWithType(b->name, NULL, DRM_NODE_RENDER);
130       if (fd < 0)
131          return NULL;
132 
133       return b->create(fd);
134    }
135 
136    return NULL;
137 }
138