xref: /aosp_15_r20/external/virglrenderer/src/vrend_winsys.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1 /**************************************************************************
2  *
3  * Copyright (C) 2014 Red Hat Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  **************************************************************************/
24 
25 #include "vrend_winsys.h"
26 
27 #ifdef HAVE_EPOXY_GLX_H
28 #include "vrend_winsys_glx.h"
29 #endif
30 
31 #include <stddef.h>
32 
33 enum {
34    CONTEXT_NONE,
35    CONTEXT_EGL,
36    CONTEXT_GLX,
37    CONTEXT_EGL_EXTERNAL
38 };
39 
40 static int use_context = CONTEXT_NONE;
41 
42 #ifdef HAVE_EPOXY_EGL_H
43 struct virgl_egl *egl = NULL;
44 struct virgl_gbm *gbm = NULL;
45 #endif
46 
47 #ifdef HAVE_EPOXY_GLX_H
48 static struct virgl_glx *glx_info = NULL;
49 #endif
50 
vrend_winsys_init(uint32_t flags,int preferred_fd)51 int vrend_winsys_init(uint32_t flags, int preferred_fd)
52 {
53    if (flags & VIRGL_RENDERER_USE_EGL) {
54 #ifdef HAVE_EPOXY_EGL_H
55       /*
56        * If the user specifies a preferred DRM fd and we can't use it, fail. If the user doesn't
57        * specify an fd, it's possible to initialize EGL without one.
58        */
59       gbm = virgl_gbm_init(preferred_fd);
60       if (preferred_fd > 0 && !gbm)
61          return -1;
62 
63       egl = virgl_egl_init(gbm, flags & VIRGL_RENDERER_USE_SURFACELESS,
64                            flags & VIRGL_RENDERER_USE_GLES);
65       if (!egl) {
66          if (gbm) {
67             virgl_gbm_fini(gbm);
68             gbm = NULL;
69          }
70 
71          return -1;
72       }
73 
74       use_context = CONTEXT_EGL;
75 #else
76       (void)preferred_fd;
77       vrend_printf( "EGL is not supported on this platform\n");
78       return -1;
79 #endif
80    } else if (flags & VIRGL_RENDERER_USE_GLX) {
81 #ifdef HAVE_EPOXY_GLX_H
82       glx_info = virgl_glx_init();
83       if (!glx_info)
84          return -1;
85       use_context = CONTEXT_GLX;
86 #else
87       vrend_printf( "GLX is not supported on this platform\n");
88       return -1;
89 #endif
90    }
91 
92    return 0;
93 }
94 
vrend_winsys_cleanup(void)95 void vrend_winsys_cleanup(void)
96 {
97 #ifdef HAVE_EPOXY_EGL_H
98    if (use_context == CONTEXT_EGL) {
99       virgl_egl_destroy(egl);
100       egl = NULL;
101       use_context = CONTEXT_NONE;
102       if (gbm) {
103          virgl_gbm_fini(gbm);
104          gbm = NULL;
105       }
106    } else if (use_context == CONTEXT_EGL_EXTERNAL) {
107       free(egl);
108       egl = NULL;
109       use_context = CONTEXT_NONE;
110    }
111 #endif
112 #ifdef HAVE_EPOXY_GLX_H
113    if (use_context == CONTEXT_GLX) {
114       virgl_glx_destroy(glx_info);
115       glx_info = NULL;
116       use_context = CONTEXT_NONE;
117    }
118 #endif
119 }
120 
vrend_winsys_init_external(void * egl_display)121 int vrend_winsys_init_external(void *egl_display)
122 {
123 #ifdef HAVE_EPOXY_EGL_H
124       egl = virgl_egl_init_external(egl_display);
125       if (!egl)
126          return -1;
127 
128       use_context = CONTEXT_EGL_EXTERNAL;
129 #else
130    (void)egl_display;
131    vrend_printf( "EGL is not supported on this platform\n");
132    return -1;
133 #endif
134 
135    return 0;
136 }
137 
vrend_winsys_create_context(struct virgl_gl_ctx_param * param)138 virgl_renderer_gl_context vrend_winsys_create_context(struct virgl_gl_ctx_param *param)
139 {
140 #ifdef HAVE_EPOXY_EGL_H
141    if (use_context == CONTEXT_EGL)
142       return virgl_egl_create_context(egl, param);
143 #endif
144 #ifdef HAVE_EPOXY_GLX_H
145    if (use_context == CONTEXT_GLX)
146       return virgl_glx_create_context(glx_info, param);
147 #endif
148    return NULL;
149 }
150 
vrend_winsys_destroy_context(virgl_renderer_gl_context ctx)151 void vrend_winsys_destroy_context(virgl_renderer_gl_context ctx)
152 {
153 #ifdef HAVE_EPOXY_EGL_H
154    if (use_context == CONTEXT_EGL) {
155       virgl_egl_destroy_context(egl, ctx);
156       return;
157    }
158 #endif
159 #ifdef HAVE_EPOXY_GLX_H
160    if (use_context == CONTEXT_GLX) {
161       virgl_glx_destroy_context(glx_info, ctx);
162       return;
163    }
164 #endif
165 }
166 
vrend_winsys_make_context_current(virgl_renderer_gl_context ctx)167 int vrend_winsys_make_context_current(virgl_renderer_gl_context ctx)
168 {
169    int ret = -1;
170 #ifdef HAVE_EPOXY_EGL_H
171    if (use_context == CONTEXT_EGL) {
172       ret = virgl_egl_make_context_current(egl, ctx);
173       if (ret)
174          vrend_printf("%s: Error switching context: %s\n",
175                       __func__, virgl_egl_error_string(eglGetError()));
176    }
177 #endif
178 #ifdef HAVE_EPOXY_GLX_H
179    if (use_context == CONTEXT_GLX) {
180       ret = virgl_glx_make_context_current(glx_info, ctx);
181       if (ret)
182          vrend_printf("%s: Error switching context\n", __func__);
183    }
184 #endif
185    assert(!ret && "Failed to switch GL context");
186    return ret;
187 }
188 
vrend_winsys_has_gl_colorspace(void)189 int vrend_winsys_has_gl_colorspace(void)
190 {
191    bool egl_colorspace = false;
192 #ifdef HAVE_EPOXY_EGL_H
193    if (egl)
194       egl_colorspace = virgl_has_egl_khr_gl_colorspace(egl);
195 #endif
196    return use_context == CONTEXT_NONE ||
197          use_context == CONTEXT_GLX ||
198          (use_context == CONTEXT_EGL && egl_colorspace) ||
199          (use_context == CONTEXT_EGL_EXTERNAL && egl_colorspace);
200 }
201 
vrend_winsys_get_fourcc_for_texture(uint32_t tex_id,uint32_t format,int * fourcc)202 int vrend_winsys_get_fourcc_for_texture(uint32_t tex_id, uint32_t format, int *fourcc)
203 {
204 #ifdef HAVE_EPOXY_EGL_H
205    if (use_context == CONTEXT_EGL)
206       return virgl_egl_get_fourcc_for_texture(egl, tex_id, format, fourcc);
207 #else
208    (void)tex_id;
209    (void)format;
210    (void)fourcc;
211 #endif
212    return 0;
213 }
214 
vrend_winsys_get_fd_for_texture(uint32_t tex_id,int * fd)215 int vrend_winsys_get_fd_for_texture(uint32_t tex_id, int *fd)
216 {
217 #ifdef HAVE_EPOXY_EGL_H
218    if (!egl)
219       return -1;
220 
221    return virgl_egl_get_fd_for_texture(egl, tex_id, fd);
222 #else
223    (void)tex_id;
224    (void)fd;
225    return -1;
226 #endif
227 }
228 
vrend_winsys_get_fd_for_texture2(uint32_t tex_id,int * fd,int * stride,int * offset)229 int vrend_winsys_get_fd_for_texture2(uint32_t tex_id, int *fd, int *stride, int *offset)
230 {
231 #ifdef HAVE_EPOXY_EGL_H
232    if (!egl)
233       return -1;
234 
235    return virgl_egl_get_fd_for_texture2(egl, tex_id, fd, stride, offset);
236 #else
237    (void)tex_id;
238    (void)fd;
239    (void)stride;
240    (void)offset;
241    return -1;
242 #endif
243 }
244 
vrend_winsys_query_video_memory(void)245 uint32_t vrend_winsys_query_video_memory(void)
246 {
247 #ifdef HAVE_EPOXY_GLX_H
248    return virgl_glx_query_video_memory(glx_info);
249 #else
250    return 0;
251 #endif
252 }
253 
254 /* different_gpu means that GBM and GL renderer are on two different DRM devices.
255  * Linear buffers are used for scanouts to make them shareable.
256  * Advise the client to use drawable shadowing for performance.
257  */
vrend_winsys_different_gpu(void)258 bool vrend_winsys_different_gpu(void)
259 {
260 #ifdef HAVE_EPOXY_EGL_H
261    if (egl)
262       return virgl_egl_different_gpu(egl);
263 #endif
264    return false;
265 }
266