xref: /aosp_15_r20/external/virglrenderer/src/vrend_winsys_egl.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1*bbecb9d1SAndroid Build Coastguard Worker /**************************************************************************
2*bbecb9d1SAndroid Build Coastguard Worker  *
3*bbecb9d1SAndroid Build Coastguard Worker  * Copyright (C) 2014 Red Hat Inc.
4*bbecb9d1SAndroid Build Coastguard Worker  *
5*bbecb9d1SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
6*bbecb9d1SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
7*bbecb9d1SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
8*bbecb9d1SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*bbecb9d1SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
10*bbecb9d1SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
11*bbecb9d1SAndroid Build Coastguard Worker  *
12*bbecb9d1SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
13*bbecb9d1SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
14*bbecb9d1SAndroid Build Coastguard Worker  *
15*bbecb9d1SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16*bbecb9d1SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*bbecb9d1SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*bbecb9d1SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19*bbecb9d1SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20*bbecb9d1SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21*bbecb9d1SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
22*bbecb9d1SAndroid Build Coastguard Worker  *
23*bbecb9d1SAndroid Build Coastguard Worker  **************************************************************************/
24*bbecb9d1SAndroid Build Coastguard Worker /* create our own EGL offscreen rendering context via gbm and rendernodes */
25*bbecb9d1SAndroid Build Coastguard Worker 
26*bbecb9d1SAndroid Build Coastguard Worker 
27*bbecb9d1SAndroid Build Coastguard Worker /* if we are using EGL and rendernodes then we talk via file descriptors to the remote
28*bbecb9d1SAndroid Build Coastguard Worker    node */
29*bbecb9d1SAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*bbecb9d1SAndroid Build Coastguard Worker #include "config.h"
31*bbecb9d1SAndroid Build Coastguard Worker #endif
32*bbecb9d1SAndroid Build Coastguard Worker 
33*bbecb9d1SAndroid Build Coastguard Worker #define EGL_EGLEXT_PROTOTYPES
34*bbecb9d1SAndroid Build Coastguard Worker #include <errno.h>
35*bbecb9d1SAndroid Build Coastguard Worker #include <fcntl.h>
36*bbecb9d1SAndroid Build Coastguard Worker #include <poll.h>
37*bbecb9d1SAndroid Build Coastguard Worker #include <stdbool.h>
38*bbecb9d1SAndroid Build Coastguard Worker #include <unistd.h>
39*bbecb9d1SAndroid Build Coastguard Worker 
40*bbecb9d1SAndroid Build Coastguard Worker #include "util/u_memory.h"
41*bbecb9d1SAndroid Build Coastguard Worker #include "virgl_hw.h"
42*bbecb9d1SAndroid Build Coastguard Worker #include "virgl_util.h"
43*bbecb9d1SAndroid Build Coastguard Worker #include "virglrenderer.h"
44*bbecb9d1SAndroid Build Coastguard Worker #include "vrend_winsys.h"
45*bbecb9d1SAndroid Build Coastguard Worker #include "vrend_winsys_egl.h"
46*bbecb9d1SAndroid Build Coastguard Worker #include "vrend_winsys_gbm.h"
47*bbecb9d1SAndroid Build Coastguard Worker 
48*bbecb9d1SAndroid Build Coastguard Worker #define EGL_KHR_SURFACELESS_CONTEXT            BIT(0)
49*bbecb9d1SAndroid Build Coastguard Worker #define EGL_KHR_CREATE_CONTEXT                 BIT(1)
50*bbecb9d1SAndroid Build Coastguard Worker #define EGL_MESA_DRM_IMAGE                     BIT(2)
51*bbecb9d1SAndroid Build Coastguard Worker #define EGL_MESA_IMAGE_DMA_BUF_EXPORT          BIT(3)
52*bbecb9d1SAndroid Build Coastguard Worker #define EGL_MESA_DMA_BUF_IMAGE_IMPORT          BIT(4)
53*bbecb9d1SAndroid Build Coastguard Worker #define EGL_KHR_GL_COLORSPACE                  BIT(5)
54*bbecb9d1SAndroid Build Coastguard Worker #define EGL_EXT_IMAGE_DMA_BUF_IMPORT           BIT(6)
55*bbecb9d1SAndroid Build Coastguard Worker #define EGL_EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS BIT(7)
56*bbecb9d1SAndroid Build Coastguard Worker #define EGL_KHR_FENCE_SYNC_ANDROID             BIT(8)
57*bbecb9d1SAndroid Build Coastguard Worker 
58*bbecb9d1SAndroid Build Coastguard Worker static const struct {
59*bbecb9d1SAndroid Build Coastguard Worker    uint32_t bit;
60*bbecb9d1SAndroid Build Coastguard Worker    const char *string;
61*bbecb9d1SAndroid Build Coastguard Worker } extensions_list[] = {
62*bbecb9d1SAndroid Build Coastguard Worker    { EGL_KHR_SURFACELESS_CONTEXT, "EGL_KHR_surfaceless_context" },
63*bbecb9d1SAndroid Build Coastguard Worker    { EGL_KHR_CREATE_CONTEXT, "EGL_KHR_create_context" },
64*bbecb9d1SAndroid Build Coastguard Worker    { EGL_MESA_DRM_IMAGE, "EGL_MESA_drm_image" },
65*bbecb9d1SAndroid Build Coastguard Worker    { EGL_MESA_IMAGE_DMA_BUF_EXPORT, "EGL_MESA_image_dma_buf_export" },
66*bbecb9d1SAndroid Build Coastguard Worker    { EGL_KHR_GL_COLORSPACE, "EGL_KHR_gl_colorspace" },
67*bbecb9d1SAndroid Build Coastguard Worker    { EGL_EXT_IMAGE_DMA_BUF_IMPORT, "EGL_EXT_image_dma_buf_import" },
68*bbecb9d1SAndroid Build Coastguard Worker    { EGL_EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS, "EGL_EXT_image_dma_buf_import_modifiers" },
69*bbecb9d1SAndroid Build Coastguard Worker    { EGL_KHR_FENCE_SYNC_ANDROID, "EGL_ANDROID_native_fence_sync"}
70*bbecb9d1SAndroid Build Coastguard Worker };
71*bbecb9d1SAndroid Build Coastguard Worker 
72*bbecb9d1SAndroid Build Coastguard Worker struct virgl_egl {
73*bbecb9d1SAndroid Build Coastguard Worker    struct virgl_gbm *gbm;
74*bbecb9d1SAndroid Build Coastguard Worker    EGLDisplay egl_display;
75*bbecb9d1SAndroid Build Coastguard Worker    EGLConfig egl_conf;
76*bbecb9d1SAndroid Build Coastguard Worker    EGLContext egl_ctx;
77*bbecb9d1SAndroid Build Coastguard Worker    uint32_t extension_bits;
78*bbecb9d1SAndroid Build Coastguard Worker    EGLSyncKHR signaled_fence;
79*bbecb9d1SAndroid Build Coastguard Worker    bool different_gpu;
80*bbecb9d1SAndroid Build Coastguard Worker };
81*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_has_extension_in_string(const char * haystack,const char * needle)82*bbecb9d1SAndroid Build Coastguard Worker static bool virgl_egl_has_extension_in_string(const char *haystack, const char *needle)
83*bbecb9d1SAndroid Build Coastguard Worker {
84*bbecb9d1SAndroid Build Coastguard Worker    const unsigned needle_len = strlen(needle);
85*bbecb9d1SAndroid Build Coastguard Worker 
86*bbecb9d1SAndroid Build Coastguard Worker    if (!haystack)
87*bbecb9d1SAndroid Build Coastguard Worker       return false;
88*bbecb9d1SAndroid Build Coastguard Worker 
89*bbecb9d1SAndroid Build Coastguard Worker    if (needle_len == 0)
90*bbecb9d1SAndroid Build Coastguard Worker       return false;
91*bbecb9d1SAndroid Build Coastguard Worker 
92*bbecb9d1SAndroid Build Coastguard Worker    while (true) {
93*bbecb9d1SAndroid Build Coastguard Worker       const char *const s = strstr(haystack, needle);
94*bbecb9d1SAndroid Build Coastguard Worker 
95*bbecb9d1SAndroid Build Coastguard Worker       if (s == NULL)
96*bbecb9d1SAndroid Build Coastguard Worker          return false;
97*bbecb9d1SAndroid Build Coastguard Worker 
98*bbecb9d1SAndroid Build Coastguard Worker       if (s[needle_len] == ' ' || s[needle_len] == '\0') {
99*bbecb9d1SAndroid Build Coastguard Worker          return true;
100*bbecb9d1SAndroid Build Coastguard Worker       }
101*bbecb9d1SAndroid Build Coastguard Worker 
102*bbecb9d1SAndroid Build Coastguard Worker       /* strstr found an extension whose name begins with
103*bbecb9d1SAndroid Build Coastguard Worker        * needle, but whose name is not equal to needle.
104*bbecb9d1SAndroid Build Coastguard Worker        * Restart the search at s + needle_len so that we
105*bbecb9d1SAndroid Build Coastguard Worker        * don't just find the same extension again and go
106*bbecb9d1SAndroid Build Coastguard Worker        * into an infinite loop.
107*bbecb9d1SAndroid Build Coastguard Worker        */
108*bbecb9d1SAndroid Build Coastguard Worker       haystack = s + needle_len;
109*bbecb9d1SAndroid Build Coastguard Worker    }
110*bbecb9d1SAndroid Build Coastguard Worker 
111*bbecb9d1SAndroid Build Coastguard Worker    return false;
112*bbecb9d1SAndroid Build Coastguard Worker }
113*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_init_extensions(struct virgl_egl * egl,const char * extensions)114*bbecb9d1SAndroid Build Coastguard Worker static int virgl_egl_init_extensions(struct virgl_egl *egl, const char *extensions)
115*bbecb9d1SAndroid Build Coastguard Worker {
116*bbecb9d1SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < ARRAY_SIZE(extensions_list); i++) {
117*bbecb9d1SAndroid Build Coastguard Worker       if (virgl_egl_has_extension_in_string(extensions, extensions_list[i].string))
118*bbecb9d1SAndroid Build Coastguard Worker          egl->extension_bits |= extensions_list[i].bit;
119*bbecb9d1SAndroid Build Coastguard Worker    }
120*bbecb9d1SAndroid Build Coastguard Worker 
121*bbecb9d1SAndroid Build Coastguard Worker    if (!has_bits(egl->extension_bits, EGL_KHR_SURFACELESS_CONTEXT | EGL_KHR_CREATE_CONTEXT)) {
122*bbecb9d1SAndroid Build Coastguard Worker       vrend_printf( "Missing EGL_KHR_surfaceless_context or EGL_KHR_create_context\n");
123*bbecb9d1SAndroid Build Coastguard Worker       return -1;
124*bbecb9d1SAndroid Build Coastguard Worker    }
125*bbecb9d1SAndroid Build Coastguard Worker 
126*bbecb9d1SAndroid Build Coastguard Worker    return 0;
127*bbecb9d1SAndroid Build Coastguard Worker }
128*bbecb9d1SAndroid Build Coastguard Worker 
129*bbecb9d1SAndroid Build Coastguard Worker #ifdef ENABLE_MINIGBM_ALLOCATION
130*bbecb9d1SAndroid Build Coastguard Worker 
131*bbecb9d1SAndroid Build Coastguard Worker struct egl_funcs {
132*bbecb9d1SAndroid Build Coastguard Worker    PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplay;
133*bbecb9d1SAndroid Build Coastguard Worker    PFNEGLQUERYDEVICESEXTPROC eglQueryDevices;
134*bbecb9d1SAndroid Build Coastguard Worker    PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceString;
135*bbecb9d1SAndroid Build Coastguard Worker };
136*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_get_interface(struct egl_funcs * funcs)137*bbecb9d1SAndroid Build Coastguard Worker static bool virgl_egl_get_interface(struct egl_funcs *funcs)
138*bbecb9d1SAndroid Build Coastguard Worker {
139*bbecb9d1SAndroid Build Coastguard Worker    const char *client_extensions = eglQueryString (NULL, EGL_EXTENSIONS);
140*bbecb9d1SAndroid Build Coastguard Worker 
141*bbecb9d1SAndroid Build Coastguard Worker    assert(funcs);
142*bbecb9d1SAndroid Build Coastguard Worker 
143*bbecb9d1SAndroid Build Coastguard Worker    if (virgl_egl_has_extension_in_string(client_extensions, "EGL_EXT_platform_base")) {
144*bbecb9d1SAndroid Build Coastguard Worker       funcs->eglGetPlatformDisplay =
145*bbecb9d1SAndroid Build Coastguard Worker          (PFNEGLGETPLATFORMDISPLAYEXTPROC) eglGetProcAddress ("eglGetPlatformDisplayEXT");
146*bbecb9d1SAndroid Build Coastguard Worker    }
147*bbecb9d1SAndroid Build Coastguard Worker 
148*bbecb9d1SAndroid Build Coastguard Worker    if (!funcs->eglGetPlatformDisplay)
149*bbecb9d1SAndroid Build Coastguard Worker       return false;
150*bbecb9d1SAndroid Build Coastguard Worker 
151*bbecb9d1SAndroid Build Coastguard Worker    if (!virgl_egl_has_extension_in_string(client_extensions, "EGL_EXT_platform_device"))
152*bbecb9d1SAndroid Build Coastguard Worker       return false;
153*bbecb9d1SAndroid Build Coastguard Worker 
154*bbecb9d1SAndroid Build Coastguard Worker    if (!virgl_egl_has_extension_in_string(client_extensions, "EGL_EXT_device_enumeration"))
155*bbecb9d1SAndroid Build Coastguard Worker       return false;
156*bbecb9d1SAndroid Build Coastguard Worker 
157*bbecb9d1SAndroid Build Coastguard Worker    funcs->eglQueryDevices = (PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress ("eglQueryDevicesEXT");
158*bbecb9d1SAndroid Build Coastguard Worker    if (!funcs->eglQueryDevices)
159*bbecb9d1SAndroid Build Coastguard Worker       return false;
160*bbecb9d1SAndroid Build Coastguard Worker 
161*bbecb9d1SAndroid Build Coastguard Worker    if (!virgl_egl_has_extension_in_string(client_extensions, "EGL_EXT_device_query"))
162*bbecb9d1SAndroid Build Coastguard Worker       return false;
163*bbecb9d1SAndroid Build Coastguard Worker 
164*bbecb9d1SAndroid Build Coastguard Worker    funcs->eglQueryDeviceString = (PFNEGLQUERYDEVICESTRINGEXTPROC)eglGetProcAddress("eglQueryDeviceStringEXT");
165*bbecb9d1SAndroid Build Coastguard Worker    if (!funcs->eglQueryDeviceString)
166*bbecb9d1SAndroid Build Coastguard Worker       return false;
167*bbecb9d1SAndroid Build Coastguard Worker 
168*bbecb9d1SAndroid Build Coastguard Worker   return true;
169*bbecb9d1SAndroid Build Coastguard Worker }
170*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_find_3d_device(struct gbm_device_info * dev_infos,EGLint num_devices,uint32_t flags)171*bbecb9d1SAndroid Build Coastguard Worker static EGLint virgl_egl_find_3d_device(struct gbm_device_info *dev_infos, EGLint num_devices, uint32_t flags)
172*bbecb9d1SAndroid Build Coastguard Worker {
173*bbecb9d1SAndroid Build Coastguard Worker    EGLint d;
174*bbecb9d1SAndroid Build Coastguard Worker 
175*bbecb9d1SAndroid Build Coastguard Worker    for (d = 0; d < num_devices; d++) {
176*bbecb9d1SAndroid Build Coastguard Worker        if ((dev_infos[d].dev_type_flags & flags) == flags
177*bbecb9d1SAndroid Build Coastguard Worker            && dev_infos[d].dev_type_flags & GBM_DEV_TYPE_FLAG_3D)
178*bbecb9d1SAndroid Build Coastguard Worker           return d;
179*bbecb9d1SAndroid Build Coastguard Worker    }
180*bbecb9d1SAndroid Build Coastguard Worker 
181*bbecb9d1SAndroid Build Coastguard Worker    return -1;
182*bbecb9d1SAndroid Build Coastguard Worker }
183*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_find_matching_device(struct gbm_device_info * dev_infos,EGLint num_devices,int dri_node_num)184*bbecb9d1SAndroid Build Coastguard Worker static EGLint virgl_egl_find_matching_device(struct gbm_device_info *dev_infos, EGLint num_devices, int dri_node_num)
185*bbecb9d1SAndroid Build Coastguard Worker {
186*bbecb9d1SAndroid Build Coastguard Worker    EGLint d;
187*bbecb9d1SAndroid Build Coastguard Worker 
188*bbecb9d1SAndroid Build Coastguard Worker    for (d = 0; d < num_devices; d++) {
189*bbecb9d1SAndroid Build Coastguard Worker        if (dev_infos[d].dri_node_num == dri_node_num)
190*bbecb9d1SAndroid Build Coastguard Worker           return d;
191*bbecb9d1SAndroid Build Coastguard Worker    }
192*bbecb9d1SAndroid Build Coastguard Worker 
193*bbecb9d1SAndroid Build Coastguard Worker    return -1;
194*bbecb9d1SAndroid Build Coastguard Worker }
195*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_get_device(struct virgl_egl * egl,struct egl_funcs * funcs)196*bbecb9d1SAndroid Build Coastguard Worker static EGLDeviceEXT virgl_egl_get_device(struct virgl_egl *egl, struct egl_funcs *funcs) {
197*bbecb9d1SAndroid Build Coastguard Worker    EGLint num_devices = 0;
198*bbecb9d1SAndroid Build Coastguard Worker    EGLint max_devices = 64;
199*bbecb9d1SAndroid Build Coastguard Worker    EGLDeviceEXT devices[64];
200*bbecb9d1SAndroid Build Coastguard Worker    struct gbm_device_info dev_infos[64];
201*bbecb9d1SAndroid Build Coastguard Worker    struct gbm_device_info gbm_dev_info;
202*bbecb9d1SAndroid Build Coastguard Worker    EGLint device_num = -1;
203*bbecb9d1SAndroid Build Coastguard Worker    EGLint d;
204*bbecb9d1SAndroid Build Coastguard Worker 
205*bbecb9d1SAndroid Build Coastguard Worker    if (gbm_detect_device_info(0, gbm_device_get_fd(egl->gbm->device), &gbm_dev_info) < 0)
206*bbecb9d1SAndroid Build Coastguard Worker       return EGL_NO_DEVICE_EXT;
207*bbecb9d1SAndroid Build Coastguard Worker 
208*bbecb9d1SAndroid Build Coastguard Worker    if (!funcs->eglQueryDevices(max_devices, devices, &num_devices))
209*bbecb9d1SAndroid Build Coastguard Worker       return EGL_NO_DEVICE_EXT;
210*bbecb9d1SAndroid Build Coastguard Worker 
211*bbecb9d1SAndroid Build Coastguard Worker    /* We query EGL_DRM_DEVICE_FILE_EXT without checking EGL_EXT_device_drm extension,
212*bbecb9d1SAndroid Build Coastguard Worker     * we just get NULL when it is not available. Otherwise we would have to query it
213*bbecb9d1SAndroid Build Coastguard Worker     * after initializing display for every device.
214*bbecb9d1SAndroid Build Coastguard Worker     */
215*bbecb9d1SAndroid Build Coastguard Worker    for (d = 0; d < num_devices; d++) {
216*bbecb9d1SAndroid Build Coastguard Worker        const char *dev_node = funcs->eglQueryDeviceString(devices[d], EGL_DRM_DEVICE_FILE_EXT);
217*bbecb9d1SAndroid Build Coastguard Worker        memset(&dev_infos[d], 0, sizeof(dev_infos[d]));
218*bbecb9d1SAndroid Build Coastguard Worker        if (dev_node) {
219*bbecb9d1SAndroid Build Coastguard Worker           if (gbm_detect_device_info_path(0, dev_node, dev_infos+d) < 0)
220*bbecb9d1SAndroid Build Coastguard Worker              return false;
221*bbecb9d1SAndroid Build Coastguard Worker        } else {
222*bbecb9d1SAndroid Build Coastguard Worker           dev_infos[d].dri_node_num = -1;
223*bbecb9d1SAndroid Build Coastguard Worker        }
224*bbecb9d1SAndroid Build Coastguard Worker    }
225*bbecb9d1SAndroid Build Coastguard Worker 
226*bbecb9d1SAndroid Build Coastguard Worker    if (getenv("VIRGL_PREFER_DGPU"))
227*bbecb9d1SAndroid Build Coastguard Worker       /* Find a discrete GPU. */
228*bbecb9d1SAndroid Build Coastguard Worker       device_num = virgl_egl_find_3d_device(dev_infos, num_devices, GBM_DEV_TYPE_FLAG_DISCRETE);
229*bbecb9d1SAndroid Build Coastguard Worker 
230*bbecb9d1SAndroid Build Coastguard Worker    if (device_num >= 0) {
231*bbecb9d1SAndroid Build Coastguard Worker       egl->different_gpu = dev_infos[device_num].dri_node_num != gbm_dev_info.dri_node_num;
232*bbecb9d1SAndroid Build Coastguard Worker    } else if (gbm_dev_info.dev_type_flags & GBM_DEV_TYPE_FLAG_ARMSOC) {
233*bbecb9d1SAndroid Build Coastguard Worker       /* Find 3D device on ARM SOC. */
234*bbecb9d1SAndroid Build Coastguard Worker       device_num = virgl_egl_find_3d_device(dev_infos, num_devices, GBM_DEV_TYPE_FLAG_ARMSOC);
235*bbecb9d1SAndroid Build Coastguard Worker    }
236*bbecb9d1SAndroid Build Coastguard Worker 
237*bbecb9d1SAndroid Build Coastguard Worker    if (device_num < 0) {
238*bbecb9d1SAndroid Build Coastguard Worker       /* Try to match GBM device. */
239*bbecb9d1SAndroid Build Coastguard Worker       device_num = virgl_egl_find_matching_device(dev_infos, num_devices, gbm_dev_info.dri_node_num);
240*bbecb9d1SAndroid Build Coastguard Worker    }
241*bbecb9d1SAndroid Build Coastguard Worker    if (device_num < 0)
242*bbecb9d1SAndroid Build Coastguard Worker       return EGL_NO_DEVICE_EXT;
243*bbecb9d1SAndroid Build Coastguard Worker 
244*bbecb9d1SAndroid Build Coastguard Worker   return devices[device_num];
245*bbecb9d1SAndroid Build Coastguard Worker }
246*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_get_display(struct virgl_egl * egl)247*bbecb9d1SAndroid Build Coastguard Worker static bool virgl_egl_get_display(struct virgl_egl *egl)
248*bbecb9d1SAndroid Build Coastguard Worker {
249*bbecb9d1SAndroid Build Coastguard Worker    struct egl_funcs funcs = { 0 };
250*bbecb9d1SAndroid Build Coastguard Worker    EGLDeviceEXT device;
251*bbecb9d1SAndroid Build Coastguard Worker 
252*bbecb9d1SAndroid Build Coastguard Worker    if (!egl->gbm)
253*bbecb9d1SAndroid Build Coastguard Worker       return false;
254*bbecb9d1SAndroid Build Coastguard Worker 
255*bbecb9d1SAndroid Build Coastguard Worker    if (!virgl_egl_get_interface(&funcs))
256*bbecb9d1SAndroid Build Coastguard Worker       return false;
257*bbecb9d1SAndroid Build Coastguard Worker 
258*bbecb9d1SAndroid Build Coastguard Worker    device = virgl_egl_get_device(egl, &funcs);
259*bbecb9d1SAndroid Build Coastguard Worker 
260*bbecb9d1SAndroid Build Coastguard Worker    if (device == EGL_NO_DEVICE_EXT)
261*bbecb9d1SAndroid Build Coastguard Worker       return false;
262*bbecb9d1SAndroid Build Coastguard Worker 
263*bbecb9d1SAndroid Build Coastguard Worker    egl->egl_display = funcs.eglGetPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, device, NULL);
264*bbecb9d1SAndroid Build Coastguard Worker    return true;
265*bbecb9d1SAndroid Build Coastguard Worker }
266*bbecb9d1SAndroid Build Coastguard Worker #endif /* ENABLE_MINIGBM_ALLOCATION */
267*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_init(struct virgl_gbm * gbm,bool surfaceless,bool gles)268*bbecb9d1SAndroid Build Coastguard Worker struct virgl_egl *virgl_egl_init(struct virgl_gbm *gbm, bool surfaceless, bool gles)
269*bbecb9d1SAndroid Build Coastguard Worker {
270*bbecb9d1SAndroid Build Coastguard Worker    static EGLint conf_att[] = {
271*bbecb9d1SAndroid Build Coastguard Worker       EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
272*bbecb9d1SAndroid Build Coastguard Worker       EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
273*bbecb9d1SAndroid Build Coastguard Worker       EGL_RED_SIZE, 1,
274*bbecb9d1SAndroid Build Coastguard Worker       EGL_GREEN_SIZE, 1,
275*bbecb9d1SAndroid Build Coastguard Worker       EGL_BLUE_SIZE, 1,
276*bbecb9d1SAndroid Build Coastguard Worker       EGL_ALPHA_SIZE, 0,
277*bbecb9d1SAndroid Build Coastguard Worker       EGL_NONE,
278*bbecb9d1SAndroid Build Coastguard Worker    };
279*bbecb9d1SAndroid Build Coastguard Worker    static const EGLint ctx_att[] = {
280*bbecb9d1SAndroid Build Coastguard Worker       EGL_CONTEXT_CLIENT_VERSION, 2,
281*bbecb9d1SAndroid Build Coastguard Worker       EGL_NONE
282*bbecb9d1SAndroid Build Coastguard Worker    };
283*bbecb9d1SAndroid Build Coastguard Worker    EGLBoolean success;
284*bbecb9d1SAndroid Build Coastguard Worker    EGLenum api;
285*bbecb9d1SAndroid Build Coastguard Worker    EGLint major, minor, num_configs;
286*bbecb9d1SAndroid Build Coastguard Worker    const char *extensions;
287*bbecb9d1SAndroid Build Coastguard Worker    struct virgl_egl *egl;
288*bbecb9d1SAndroid Build Coastguard Worker 
289*bbecb9d1SAndroid Build Coastguard Worker    egl = calloc(1, sizeof(struct virgl_egl));
290*bbecb9d1SAndroid Build Coastguard Worker    if (!egl)
291*bbecb9d1SAndroid Build Coastguard Worker       return NULL;
292*bbecb9d1SAndroid Build Coastguard Worker 
293*bbecb9d1SAndroid Build Coastguard Worker    if (gles)
294*bbecb9d1SAndroid Build Coastguard Worker       conf_att[3] = EGL_OPENGL_ES2_BIT;
295*bbecb9d1SAndroid Build Coastguard Worker 
296*bbecb9d1SAndroid Build Coastguard Worker    if (surfaceless)
297*bbecb9d1SAndroid Build Coastguard Worker       conf_att[1] = EGL_PBUFFER_BIT;
298*bbecb9d1SAndroid Build Coastguard Worker    else if (!gbm)
299*bbecb9d1SAndroid Build Coastguard Worker       goto fail;
300*bbecb9d1SAndroid Build Coastguard Worker 
301*bbecb9d1SAndroid Build Coastguard Worker    egl->gbm = gbm;
302*bbecb9d1SAndroid Build Coastguard Worker    egl->different_gpu = false;
303*bbecb9d1SAndroid Build Coastguard Worker    const char *client_extensions = eglQueryString (NULL, EGL_EXTENSIONS);
304*bbecb9d1SAndroid Build Coastguard Worker 
305*bbecb9d1SAndroid Build Coastguard Worker #ifdef ENABLE_MINIGBM_ALLOCATION
306*bbecb9d1SAndroid Build Coastguard Worker    if (virgl_egl_get_display(egl)) {
307*bbecb9d1SAndroid Build Coastguard Worker      /* Make -Wdangling-else happy. */
308*bbecb9d1SAndroid Build Coastguard Worker    } else /* Fallback to surfaceless. */
309*bbecb9d1SAndroid Build Coastguard Worker #endif
310*bbecb9d1SAndroid Build Coastguard Worker    if (virgl_egl_has_extension_in_string(client_extensions, "EGL_EXT_platform_base")) {
311*bbecb9d1SAndroid Build Coastguard Worker       PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display =
312*bbecb9d1SAndroid Build Coastguard Worker          (PFNEGLGETPLATFORMDISPLAYEXTPROC) eglGetProcAddress ("eglGetPlatformDisplayEXT");
313*bbecb9d1SAndroid Build Coastguard Worker 
314*bbecb9d1SAndroid Build Coastguard Worker       if (!get_platform_display)
315*bbecb9d1SAndroid Build Coastguard Worker         goto fail;
316*bbecb9d1SAndroid Build Coastguard Worker 
317*bbecb9d1SAndroid Build Coastguard Worker       if (surfaceless) {
318*bbecb9d1SAndroid Build Coastguard Worker          egl->egl_display = get_platform_display (EGL_PLATFORM_SURFACELESS_MESA,
319*bbecb9d1SAndroid Build Coastguard Worker                                                   EGL_DEFAULT_DISPLAY, NULL);
320*bbecb9d1SAndroid Build Coastguard Worker       } else
321*bbecb9d1SAndroid Build Coastguard Worker          egl->egl_display = get_platform_display (EGL_PLATFORM_GBM_KHR,
322*bbecb9d1SAndroid Build Coastguard Worker                                                  (EGLNativeDisplayType)egl->gbm->device, NULL);
323*bbecb9d1SAndroid Build Coastguard Worker    } else {
324*bbecb9d1SAndroid Build Coastguard Worker       if (egl->gbm && egl->gbm->device) {
325*bbecb9d1SAndroid Build Coastguard Worker         egl->egl_display = eglGetDisplay((EGLNativeDisplayType)egl->gbm->device);
326*bbecb9d1SAndroid Build Coastguard Worker       }
327*bbecb9d1SAndroid Build Coastguard Worker    }
328*bbecb9d1SAndroid Build Coastguard Worker 
329*bbecb9d1SAndroid Build Coastguard Worker    if (!egl->egl_display) {
330*bbecb9d1SAndroid Build Coastguard Worker       /*
331*bbecb9d1SAndroid Build Coastguard Worker        * Don't fallback to the default display if the fd provided by (*get_drm_fd)
332*bbecb9d1SAndroid Build Coastguard Worker        * can't be used.
333*bbecb9d1SAndroid Build Coastguard Worker        */
334*bbecb9d1SAndroid Build Coastguard Worker       if (egl->gbm && egl->gbm->fd < 0)
335*bbecb9d1SAndroid Build Coastguard Worker          goto fail;
336*bbecb9d1SAndroid Build Coastguard Worker 
337*bbecb9d1SAndroid Build Coastguard Worker       egl->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
338*bbecb9d1SAndroid Build Coastguard Worker       if (!egl->egl_display)
339*bbecb9d1SAndroid Build Coastguard Worker          goto fail;
340*bbecb9d1SAndroid Build Coastguard Worker    }
341*bbecb9d1SAndroid Build Coastguard Worker 
342*bbecb9d1SAndroid Build Coastguard Worker    success = eglInitialize(egl->egl_display, &major, &minor);
343*bbecb9d1SAndroid Build Coastguard Worker    if (!success)
344*bbecb9d1SAndroid Build Coastguard Worker       goto fail;
345*bbecb9d1SAndroid Build Coastguard Worker 
346*bbecb9d1SAndroid Build Coastguard Worker    extensions = eglQueryString(egl->egl_display, EGL_EXTENSIONS);
347*bbecb9d1SAndroid Build Coastguard Worker #ifdef VIRGL_EGL_DEBUG
348*bbecb9d1SAndroid Build Coastguard Worker    vrend_printf( "EGL major/minor: %d.%d\n", major, minor);
349*bbecb9d1SAndroid Build Coastguard Worker    vrend_printf( "EGL version: %s\n",
350*bbecb9d1SAndroid Build Coastguard Worker            eglQueryString(egl->egl_display, EGL_VERSION));
351*bbecb9d1SAndroid Build Coastguard Worker    vrend_printf( "EGL vendor: %s\n",
352*bbecb9d1SAndroid Build Coastguard Worker            eglQueryString(egl->egl_display, EGL_VENDOR));
353*bbecb9d1SAndroid Build Coastguard Worker    vrend_printf( "EGL extensions: %s\n", extensions);
354*bbecb9d1SAndroid Build Coastguard Worker #endif
355*bbecb9d1SAndroid Build Coastguard Worker 
356*bbecb9d1SAndroid Build Coastguard Worker    if (virgl_egl_init_extensions(egl, extensions))
357*bbecb9d1SAndroid Build Coastguard Worker       goto fail;
358*bbecb9d1SAndroid Build Coastguard Worker 
359*bbecb9d1SAndroid Build Coastguard Worker    if (gles)
360*bbecb9d1SAndroid Build Coastguard Worker       api = EGL_OPENGL_ES_API;
361*bbecb9d1SAndroid Build Coastguard Worker    else
362*bbecb9d1SAndroid Build Coastguard Worker       api = EGL_OPENGL_API;
363*bbecb9d1SAndroid Build Coastguard Worker    success = eglBindAPI(api);
364*bbecb9d1SAndroid Build Coastguard Worker    if (!success)
365*bbecb9d1SAndroid Build Coastguard Worker       goto fail;
366*bbecb9d1SAndroid Build Coastguard Worker 
367*bbecb9d1SAndroid Build Coastguard Worker    success = eglChooseConfig(egl->egl_display, conf_att, &egl->egl_conf,
368*bbecb9d1SAndroid Build Coastguard Worker                              1, &num_configs);
369*bbecb9d1SAndroid Build Coastguard Worker    if (!success || num_configs != 1)
370*bbecb9d1SAndroid Build Coastguard Worker       goto fail;
371*bbecb9d1SAndroid Build Coastguard Worker 
372*bbecb9d1SAndroid Build Coastguard Worker    egl->egl_ctx = eglCreateContext(egl->egl_display, egl->egl_conf, EGL_NO_CONTEXT,
373*bbecb9d1SAndroid Build Coastguard Worker                                    ctx_att);
374*bbecb9d1SAndroid Build Coastguard Worker    if (!egl->egl_ctx)
375*bbecb9d1SAndroid Build Coastguard Worker       goto fail;
376*bbecb9d1SAndroid Build Coastguard Worker 
377*bbecb9d1SAndroid Build Coastguard Worker    eglMakeCurrent(egl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
378*bbecb9d1SAndroid Build Coastguard Worker                   egl->egl_ctx);
379*bbecb9d1SAndroid Build Coastguard Worker 
380*bbecb9d1SAndroid Build Coastguard Worker    if (gles && virgl_egl_supports_fences(egl)) {
381*bbecb9d1SAndroid Build Coastguard Worker       egl->signaled_fence = eglCreateSyncKHR(egl->egl_display,
382*bbecb9d1SAndroid Build Coastguard Worker                                              EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
383*bbecb9d1SAndroid Build Coastguard Worker       if (!egl->signaled_fence) {
384*bbecb9d1SAndroid Build Coastguard Worker          vrend_printf("Failed to create signaled fence");
385*bbecb9d1SAndroid Build Coastguard Worker          goto fail;
386*bbecb9d1SAndroid Build Coastguard Worker       }
387*bbecb9d1SAndroid Build Coastguard Worker    }
388*bbecb9d1SAndroid Build Coastguard Worker 
389*bbecb9d1SAndroid Build Coastguard Worker    return egl;
390*bbecb9d1SAndroid Build Coastguard Worker 
391*bbecb9d1SAndroid Build Coastguard Worker  fail:
392*bbecb9d1SAndroid Build Coastguard Worker    free(egl);
393*bbecb9d1SAndroid Build Coastguard Worker    return NULL;
394*bbecb9d1SAndroid Build Coastguard Worker }
395*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_destroy(struct virgl_egl * egl)396*bbecb9d1SAndroid Build Coastguard Worker void virgl_egl_destroy(struct virgl_egl *egl)
397*bbecb9d1SAndroid Build Coastguard Worker {
398*bbecb9d1SAndroid Build Coastguard Worker    if (egl->signaled_fence) {
399*bbecb9d1SAndroid Build Coastguard Worker       eglDestroySyncKHR(egl->egl_display, egl->signaled_fence);
400*bbecb9d1SAndroid Build Coastguard Worker    }
401*bbecb9d1SAndroid Build Coastguard Worker    eglMakeCurrent(egl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
402*bbecb9d1SAndroid Build Coastguard Worker                   EGL_NO_CONTEXT);
403*bbecb9d1SAndroid Build Coastguard Worker    eglDestroyContext(egl->egl_display, egl->egl_ctx);
404*bbecb9d1SAndroid Build Coastguard Worker    eglTerminate(egl->egl_display);
405*bbecb9d1SAndroid Build Coastguard Worker    free(egl);
406*bbecb9d1SAndroid Build Coastguard Worker }
407*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_init_external(EGLDisplay egl_display)408*bbecb9d1SAndroid Build Coastguard Worker struct virgl_egl *virgl_egl_init_external(EGLDisplay egl_display)
409*bbecb9d1SAndroid Build Coastguard Worker {
410*bbecb9d1SAndroid Build Coastguard Worker    const char *extensions;
411*bbecb9d1SAndroid Build Coastguard Worker    struct virgl_egl *egl;
412*bbecb9d1SAndroid Build Coastguard Worker 
413*bbecb9d1SAndroid Build Coastguard Worker    egl = calloc(1, sizeof(struct virgl_egl));
414*bbecb9d1SAndroid Build Coastguard Worker    if (!egl)
415*bbecb9d1SAndroid Build Coastguard Worker       return NULL;
416*bbecb9d1SAndroid Build Coastguard Worker 
417*bbecb9d1SAndroid Build Coastguard Worker    egl->egl_display = egl_display;
418*bbecb9d1SAndroid Build Coastguard Worker 
419*bbecb9d1SAndroid Build Coastguard Worker    extensions = eglQueryString(egl->egl_display, EGL_EXTENSIONS);
420*bbecb9d1SAndroid Build Coastguard Worker #ifdef VIRGL_EGL_DEBUG
421*bbecb9d1SAndroid Build Coastguard Worker    vrend_printf( "EGL version: %s\n",
422*bbecb9d1SAndroid Build Coastguard Worker            eglQueryString(egl->egl_display, EGL_VERSION));
423*bbecb9d1SAndroid Build Coastguard Worker    vrend_printf( "EGL vendor: %s\n",
424*bbecb9d1SAndroid Build Coastguard Worker            eglQueryString(egl->egl_display, EGL_VENDOR));
425*bbecb9d1SAndroid Build Coastguard Worker    vrend_printf( "EGL extensions: %s\n", extensions);
426*bbecb9d1SAndroid Build Coastguard Worker #endif
427*bbecb9d1SAndroid Build Coastguard Worker 
428*bbecb9d1SAndroid Build Coastguard Worker    if (virgl_egl_init_extensions(egl, extensions)) {
429*bbecb9d1SAndroid Build Coastguard Worker       free(egl);
430*bbecb9d1SAndroid Build Coastguard Worker       return NULL;
431*bbecb9d1SAndroid Build Coastguard Worker    }
432*bbecb9d1SAndroid Build Coastguard Worker 
433*bbecb9d1SAndroid Build Coastguard Worker    gbm = virgl_gbm_init(-1);
434*bbecb9d1SAndroid Build Coastguard Worker    egl->gbm = gbm;
435*bbecb9d1SAndroid Build Coastguard Worker 
436*bbecb9d1SAndroid Build Coastguard Worker    return egl;
437*bbecb9d1SAndroid Build Coastguard Worker }
438*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_create_context(struct virgl_egl * egl,struct virgl_gl_ctx_param * vparams)439*bbecb9d1SAndroid Build Coastguard Worker virgl_renderer_gl_context virgl_egl_create_context(struct virgl_egl *egl, struct virgl_gl_ctx_param *vparams)
440*bbecb9d1SAndroid Build Coastguard Worker {
441*bbecb9d1SAndroid Build Coastguard Worker    EGLContext egl_ctx;
442*bbecb9d1SAndroid Build Coastguard Worker    EGLint ctx_att[] = {
443*bbecb9d1SAndroid Build Coastguard Worker       EGL_CONTEXT_CLIENT_VERSION, vparams->major_ver,
444*bbecb9d1SAndroid Build Coastguard Worker       EGL_CONTEXT_MINOR_VERSION_KHR, vparams->minor_ver,
445*bbecb9d1SAndroid Build Coastguard Worker       EGL_NONE
446*bbecb9d1SAndroid Build Coastguard Worker    };
447*bbecb9d1SAndroid Build Coastguard Worker    egl_ctx = eglCreateContext(egl->egl_display,
448*bbecb9d1SAndroid Build Coastguard Worker                              egl->egl_conf,
449*bbecb9d1SAndroid Build Coastguard Worker                              vparams->shared ? eglGetCurrentContext() : EGL_NO_CONTEXT,
450*bbecb9d1SAndroid Build Coastguard Worker                              ctx_att);
451*bbecb9d1SAndroid Build Coastguard Worker    return (virgl_renderer_gl_context)egl_ctx;
452*bbecb9d1SAndroid Build Coastguard Worker }
453*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_destroy_context(struct virgl_egl * egl,virgl_renderer_gl_context virglctx)454*bbecb9d1SAndroid Build Coastguard Worker void virgl_egl_destroy_context(struct virgl_egl *egl, virgl_renderer_gl_context virglctx)
455*bbecb9d1SAndroid Build Coastguard Worker {
456*bbecb9d1SAndroid Build Coastguard Worker    EGLContext egl_ctx = (EGLContext)virglctx;
457*bbecb9d1SAndroid Build Coastguard Worker    eglDestroyContext(egl->egl_display, egl_ctx);
458*bbecb9d1SAndroid Build Coastguard Worker }
459*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_make_context_current(struct virgl_egl * egl,virgl_renderer_gl_context virglctx)460*bbecb9d1SAndroid Build Coastguard Worker int virgl_egl_make_context_current(struct virgl_egl *egl, virgl_renderer_gl_context virglctx)
461*bbecb9d1SAndroid Build Coastguard Worker {
462*bbecb9d1SAndroid Build Coastguard Worker    EGLContext egl_ctx = (EGLContext)virglctx;
463*bbecb9d1SAndroid Build Coastguard Worker 
464*bbecb9d1SAndroid Build Coastguard Worker    return eglMakeCurrent(egl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
465*bbecb9d1SAndroid Build Coastguard Worker                          egl_ctx) ? 0 : -1;
466*bbecb9d1SAndroid Build Coastguard Worker }
467*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_get_current_context(UNUSED struct virgl_egl * egl)468*bbecb9d1SAndroid Build Coastguard Worker virgl_renderer_gl_context virgl_egl_get_current_context(UNUSED struct virgl_egl *egl)
469*bbecb9d1SAndroid Build Coastguard Worker {
470*bbecb9d1SAndroid Build Coastguard Worker    EGLContext egl_ctx = eglGetCurrentContext();
471*bbecb9d1SAndroid Build Coastguard Worker    return (virgl_renderer_gl_context)egl_ctx;
472*bbecb9d1SAndroid Build Coastguard Worker }
473*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_get_fourcc_for_texture(struct virgl_egl * egl,uint32_t tex_id,uint32_t format,int * fourcc)474*bbecb9d1SAndroid Build Coastguard Worker int virgl_egl_get_fourcc_for_texture(struct virgl_egl *egl, uint32_t tex_id, uint32_t format, int *fourcc)
475*bbecb9d1SAndroid Build Coastguard Worker {
476*bbecb9d1SAndroid Build Coastguard Worker    int ret = EINVAL;
477*bbecb9d1SAndroid Build Coastguard Worker    uint32_t gbm_format = 0;
478*bbecb9d1SAndroid Build Coastguard Worker 
479*bbecb9d1SAndroid Build Coastguard Worker    EGLImageKHR image;
480*bbecb9d1SAndroid Build Coastguard Worker    EGLBoolean success;
481*bbecb9d1SAndroid Build Coastguard Worker 
482*bbecb9d1SAndroid Build Coastguard Worker    if (!has_bit(egl->extension_bits, EGL_MESA_IMAGE_DMA_BUF_EXPORT)) {
483*bbecb9d1SAndroid Build Coastguard Worker       ret = 0;
484*bbecb9d1SAndroid Build Coastguard Worker       goto fallback;
485*bbecb9d1SAndroid Build Coastguard Worker    }
486*bbecb9d1SAndroid Build Coastguard Worker 
487*bbecb9d1SAndroid Build Coastguard Worker    image = eglCreateImageKHR(egl->egl_display, eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
488*bbecb9d1SAndroid Build Coastguard Worker                             (EGLClientBuffer)(uintptr_t)tex_id, NULL);
489*bbecb9d1SAndroid Build Coastguard Worker 
490*bbecb9d1SAndroid Build Coastguard Worker    if (!image)
491*bbecb9d1SAndroid Build Coastguard Worker       return EINVAL;
492*bbecb9d1SAndroid Build Coastguard Worker 
493*bbecb9d1SAndroid Build Coastguard Worker    success = eglExportDMABUFImageQueryMESA(egl->egl_display, image, fourcc, NULL, NULL);
494*bbecb9d1SAndroid Build Coastguard Worker    if (!success)
495*bbecb9d1SAndroid Build Coastguard Worker       goto out_destroy;
496*bbecb9d1SAndroid Build Coastguard Worker    ret = 0;
497*bbecb9d1SAndroid Build Coastguard Worker  out_destroy:
498*bbecb9d1SAndroid Build Coastguard Worker    eglDestroyImageKHR(egl->egl_display, image);
499*bbecb9d1SAndroid Build Coastguard Worker    return ret;
500*bbecb9d1SAndroid Build Coastguard Worker 
501*bbecb9d1SAndroid Build Coastguard Worker  fallback:
502*bbecb9d1SAndroid Build Coastguard Worker    ret = virgl_gbm_convert_format(&format, &gbm_format);
503*bbecb9d1SAndroid Build Coastguard Worker    *fourcc = (int)gbm_format;
504*bbecb9d1SAndroid Build Coastguard Worker    return ret;
505*bbecb9d1SAndroid Build Coastguard Worker }
506*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_get_fd_for_texture2(struct virgl_egl * egl,uint32_t tex_id,int * fd,int * stride,int * offset)507*bbecb9d1SAndroid Build Coastguard Worker int virgl_egl_get_fd_for_texture2(struct virgl_egl *egl, uint32_t tex_id, int *fd,
508*bbecb9d1SAndroid Build Coastguard Worker                                   int *stride, int *offset)
509*bbecb9d1SAndroid Build Coastguard Worker {
510*bbecb9d1SAndroid Build Coastguard Worker    int ret = EINVAL;
511*bbecb9d1SAndroid Build Coastguard Worker    EGLImageKHR image = eglCreateImageKHR(egl->egl_display, eglGetCurrentContext(),
512*bbecb9d1SAndroid Build Coastguard Worker                                          EGL_GL_TEXTURE_2D_KHR,
513*bbecb9d1SAndroid Build Coastguard Worker                                          (EGLClientBuffer)(uintptr_t)tex_id, NULL);
514*bbecb9d1SAndroid Build Coastguard Worker    if (!image)
515*bbecb9d1SAndroid Build Coastguard Worker       return EINVAL;
516*bbecb9d1SAndroid Build Coastguard Worker    if (!has_bit(egl->extension_bits, EGL_MESA_IMAGE_DMA_BUF_EXPORT))
517*bbecb9d1SAndroid Build Coastguard Worker       goto out_destroy;
518*bbecb9d1SAndroid Build Coastguard Worker 
519*bbecb9d1SAndroid Build Coastguard Worker    if (!eglExportDMABUFImageMESA(egl->egl_display, image, fd,
520*bbecb9d1SAndroid Build Coastguard Worker                                  stride, offset))
521*bbecb9d1SAndroid Build Coastguard Worker       goto out_destroy;
522*bbecb9d1SAndroid Build Coastguard Worker 
523*bbecb9d1SAndroid Build Coastguard Worker    ret = 0;
524*bbecb9d1SAndroid Build Coastguard Worker 
525*bbecb9d1SAndroid Build Coastguard Worker out_destroy:
526*bbecb9d1SAndroid Build Coastguard Worker    eglDestroyImageKHR(egl->egl_display, image);
527*bbecb9d1SAndroid Build Coastguard Worker    return ret;
528*bbecb9d1SAndroid Build Coastguard Worker }
529*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_get_fd_for_texture(struct virgl_egl * egl,uint32_t tex_id,int * fd)530*bbecb9d1SAndroid Build Coastguard Worker int virgl_egl_get_fd_for_texture(struct virgl_egl *egl, uint32_t tex_id, int *fd)
531*bbecb9d1SAndroid Build Coastguard Worker {
532*bbecb9d1SAndroid Build Coastguard Worker    EGLImageKHR image;
533*bbecb9d1SAndroid Build Coastguard Worker    EGLint stride;
534*bbecb9d1SAndroid Build Coastguard Worker    EGLint offset;
535*bbecb9d1SAndroid Build Coastguard Worker    EGLBoolean success;
536*bbecb9d1SAndroid Build Coastguard Worker    int ret;
537*bbecb9d1SAndroid Build Coastguard Worker    image = eglCreateImageKHR(egl->egl_display, eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR,
538*bbecb9d1SAndroid Build Coastguard Worker                             (EGLClientBuffer)(uintptr_t)tex_id, NULL);
539*bbecb9d1SAndroid Build Coastguard Worker 
540*bbecb9d1SAndroid Build Coastguard Worker    if (!image)
541*bbecb9d1SAndroid Build Coastguard Worker       return EINVAL;
542*bbecb9d1SAndroid Build Coastguard Worker 
543*bbecb9d1SAndroid Build Coastguard Worker    ret = EINVAL;
544*bbecb9d1SAndroid Build Coastguard Worker    if (has_bit(egl->extension_bits, EGL_MESA_IMAGE_DMA_BUF_EXPORT)) {
545*bbecb9d1SAndroid Build Coastguard Worker       success = eglExportDMABUFImageMESA(egl->egl_display, image, fd, &stride,
546*bbecb9d1SAndroid Build Coastguard Worker                                          &offset);
547*bbecb9d1SAndroid Build Coastguard Worker       if (!success)
548*bbecb9d1SAndroid Build Coastguard Worker          goto out_destroy;
549*bbecb9d1SAndroid Build Coastguard Worker    } else if (has_bit(egl->extension_bits, EGL_MESA_DRM_IMAGE)) {
550*bbecb9d1SAndroid Build Coastguard Worker       EGLint handle;
551*bbecb9d1SAndroid Build Coastguard Worker       success = eglExportDRMImageMESA(egl->egl_display, image, NULL, &handle,
552*bbecb9d1SAndroid Build Coastguard Worker                                       &stride);
553*bbecb9d1SAndroid Build Coastguard Worker 
554*bbecb9d1SAndroid Build Coastguard Worker       if (!success)
555*bbecb9d1SAndroid Build Coastguard Worker          goto out_destroy;
556*bbecb9d1SAndroid Build Coastguard Worker 
557*bbecb9d1SAndroid Build Coastguard Worker       if (!egl->gbm)
558*bbecb9d1SAndroid Build Coastguard Worker          goto out_destroy;
559*bbecb9d1SAndroid Build Coastguard Worker 
560*bbecb9d1SAndroid Build Coastguard Worker       ret = virgl_gbm_export_fd(egl->gbm->device, handle, fd);
561*bbecb9d1SAndroid Build Coastguard Worker       if (ret < 0)
562*bbecb9d1SAndroid Build Coastguard Worker          goto out_destroy;
563*bbecb9d1SAndroid Build Coastguard Worker    } else {
564*bbecb9d1SAndroid Build Coastguard Worker       goto out_destroy;
565*bbecb9d1SAndroid Build Coastguard Worker    }
566*bbecb9d1SAndroid Build Coastguard Worker 
567*bbecb9d1SAndroid Build Coastguard Worker    ret = 0;
568*bbecb9d1SAndroid Build Coastguard Worker  out_destroy:
569*bbecb9d1SAndroid Build Coastguard Worker    eglDestroyImageKHR(egl->egl_display, image);
570*bbecb9d1SAndroid Build Coastguard Worker    return ret;
571*bbecb9d1SAndroid Build Coastguard Worker }
572*bbecb9d1SAndroid Build Coastguard Worker 
virgl_has_egl_khr_gl_colorspace(struct virgl_egl * egl)573*bbecb9d1SAndroid Build Coastguard Worker bool virgl_has_egl_khr_gl_colorspace(struct virgl_egl *egl)
574*bbecb9d1SAndroid Build Coastguard Worker {
575*bbecb9d1SAndroid Build Coastguard Worker    return has_bit(egl->extension_bits, EGL_KHR_GL_COLORSPACE);
576*bbecb9d1SAndroid Build Coastguard Worker }
577*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_image_from_dmabuf(struct virgl_egl * egl,uint32_t width,uint32_t height,uint32_t drm_format,uint64_t drm_modifier,uint32_t plane_count,const int * plane_fds,const uint32_t * plane_strides,const uint32_t * plane_offsets)578*bbecb9d1SAndroid Build Coastguard Worker void *virgl_egl_image_from_dmabuf(struct virgl_egl *egl,
579*bbecb9d1SAndroid Build Coastguard Worker                                   uint32_t width,
580*bbecb9d1SAndroid Build Coastguard Worker                                   uint32_t height,
581*bbecb9d1SAndroid Build Coastguard Worker                                   uint32_t drm_format,
582*bbecb9d1SAndroid Build Coastguard Worker                                   uint64_t drm_modifier,
583*bbecb9d1SAndroid Build Coastguard Worker                                   uint32_t plane_count,
584*bbecb9d1SAndroid Build Coastguard Worker                                   const int *plane_fds,
585*bbecb9d1SAndroid Build Coastguard Worker                                   const uint32_t *plane_strides,
586*bbecb9d1SAndroid Build Coastguard Worker                                   const uint32_t *plane_offsets)
587*bbecb9d1SAndroid Build Coastguard Worker {
588*bbecb9d1SAndroid Build Coastguard Worker    EGLint attrs[6 + VIRGL_GBM_MAX_PLANES * 10 + 1];
589*bbecb9d1SAndroid Build Coastguard Worker    uint32_t count;
590*bbecb9d1SAndroid Build Coastguard Worker 
591*bbecb9d1SAndroid Build Coastguard Worker    assert(VIRGL_GBM_MAX_PLANES <= 4);
592*bbecb9d1SAndroid Build Coastguard Worker    assert(plane_count && plane_count <= VIRGL_GBM_MAX_PLANES);
593*bbecb9d1SAndroid Build Coastguard Worker 
594*bbecb9d1SAndroid Build Coastguard Worker    count = 0;
595*bbecb9d1SAndroid Build Coastguard Worker    attrs[count++] = EGL_WIDTH;
596*bbecb9d1SAndroid Build Coastguard Worker    attrs[count++] = width;
597*bbecb9d1SAndroid Build Coastguard Worker    attrs[count++] = EGL_HEIGHT;
598*bbecb9d1SAndroid Build Coastguard Worker    attrs[count++] = height;
599*bbecb9d1SAndroid Build Coastguard Worker    attrs[count++] = EGL_LINUX_DRM_FOURCC_EXT;
600*bbecb9d1SAndroid Build Coastguard Worker    attrs[count++] = drm_format;
601*bbecb9d1SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < plane_count; i++) {
602*bbecb9d1SAndroid Build Coastguard Worker       if (i < 3) {
603*bbecb9d1SAndroid Build Coastguard Worker          attrs[count++] = EGL_DMA_BUF_PLANE0_FD_EXT + i * 3;
604*bbecb9d1SAndroid Build Coastguard Worker          attrs[count++] = plane_fds[i];
605*bbecb9d1SAndroid Build Coastguard Worker          attrs[count++] = EGL_DMA_BUF_PLANE0_PITCH_EXT + i * 3;
606*bbecb9d1SAndroid Build Coastguard Worker          attrs[count++] = plane_strides[i];
607*bbecb9d1SAndroid Build Coastguard Worker          attrs[count++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT + i * 3;
608*bbecb9d1SAndroid Build Coastguard Worker          attrs[count++] = plane_offsets[i];
609*bbecb9d1SAndroid Build Coastguard Worker       }
610*bbecb9d1SAndroid Build Coastguard Worker 
611*bbecb9d1SAndroid Build Coastguard Worker       if (has_bit(egl->extension_bits, EGL_EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS)) {
612*bbecb9d1SAndroid Build Coastguard Worker          if (i == 3) {
613*bbecb9d1SAndroid Build Coastguard Worker             attrs[count++] = EGL_DMA_BUF_PLANE3_FD_EXT;
614*bbecb9d1SAndroid Build Coastguard Worker             attrs[count++] = plane_fds[i];
615*bbecb9d1SAndroid Build Coastguard Worker             attrs[count++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
616*bbecb9d1SAndroid Build Coastguard Worker             attrs[count++] = plane_strides[i];
617*bbecb9d1SAndroid Build Coastguard Worker             attrs[count++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
618*bbecb9d1SAndroid Build Coastguard Worker             attrs[count++] = plane_offsets[i];
619*bbecb9d1SAndroid Build Coastguard Worker          }
620*bbecb9d1SAndroid Build Coastguard Worker 
621*bbecb9d1SAndroid Build Coastguard Worker 	 if (drm_modifier != DRM_FORMAT_MOD_INVALID) {
622*bbecb9d1SAndroid Build Coastguard Worker             attrs[count++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT + i * 2;
623*bbecb9d1SAndroid Build Coastguard Worker             attrs[count++] = (uint32_t)drm_modifier;
624*bbecb9d1SAndroid Build Coastguard Worker             attrs[count++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT + i * 2;
625*bbecb9d1SAndroid Build Coastguard Worker             attrs[count++] = (uint32_t)(drm_modifier >> 32);
626*bbecb9d1SAndroid Build Coastguard Worker 	 }
627*bbecb9d1SAndroid Build Coastguard Worker       }
628*bbecb9d1SAndroid Build Coastguard Worker    }
629*bbecb9d1SAndroid Build Coastguard Worker    attrs[count++] = EGL_NONE;
630*bbecb9d1SAndroid Build Coastguard Worker    assert(count <= ARRAY_SIZE(attrs));
631*bbecb9d1SAndroid Build Coastguard Worker 
632*bbecb9d1SAndroid Build Coastguard Worker    return (void *)eglCreateImageKHR(egl->egl_display,
633*bbecb9d1SAndroid Build Coastguard Worker                                     EGL_NO_CONTEXT,
634*bbecb9d1SAndroid Build Coastguard Worker                                     EGL_LINUX_DMA_BUF_EXT,
635*bbecb9d1SAndroid Build Coastguard Worker                                     (EGLClientBuffer)NULL,
636*bbecb9d1SAndroid Build Coastguard Worker                                     attrs);
637*bbecb9d1SAndroid Build Coastguard Worker }
638*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_image_destroy(struct virgl_egl * egl,void * image)639*bbecb9d1SAndroid Build Coastguard Worker void virgl_egl_image_destroy(struct virgl_egl *egl, void *image)
640*bbecb9d1SAndroid Build Coastguard Worker {
641*bbecb9d1SAndroid Build Coastguard Worker    eglDestroyImageKHR(egl->egl_display, image);
642*bbecb9d1SAndroid Build Coastguard Worker }
643*bbecb9d1SAndroid Build Coastguard Worker 
644*bbecb9d1SAndroid Build Coastguard Worker #ifdef ENABLE_MINIGBM_ALLOCATION
virgl_egl_image_from_gbm_bo(struct virgl_egl * egl,struct gbm_bo * bo)645*bbecb9d1SAndroid Build Coastguard Worker void *virgl_egl_image_from_gbm_bo(struct virgl_egl *egl, struct gbm_bo *bo)
646*bbecb9d1SAndroid Build Coastguard Worker {
647*bbecb9d1SAndroid Build Coastguard Worker    int ret;
648*bbecb9d1SAndroid Build Coastguard Worker    void *image = NULL;
649*bbecb9d1SAndroid Build Coastguard Worker    int fds[VIRGL_GBM_MAX_PLANES] = {-1, -1, -1, -1};
650*bbecb9d1SAndroid Build Coastguard Worker    uint32_t strides[VIRGL_GBM_MAX_PLANES];
651*bbecb9d1SAndroid Build Coastguard Worker    uint32_t offsets[VIRGL_GBM_MAX_PLANES];
652*bbecb9d1SAndroid Build Coastguard Worker    int num_planes = gbm_bo_get_plane_count(bo);
653*bbecb9d1SAndroid Build Coastguard Worker 
654*bbecb9d1SAndroid Build Coastguard Worker    if (num_planes < 0 || num_planes > VIRGL_GBM_MAX_PLANES)
655*bbecb9d1SAndroid Build Coastguard Worker       return NULL;
656*bbecb9d1SAndroid Build Coastguard Worker 
657*bbecb9d1SAndroid Build Coastguard Worker    for (int plane = 0; plane < num_planes; plane++) {
658*bbecb9d1SAndroid Build Coastguard Worker       uint32_t handle = gbm_bo_get_handle_for_plane(bo, plane).u32;
659*bbecb9d1SAndroid Build Coastguard Worker       ret = virgl_gbm_export_fd(egl->gbm->device, handle, &fds[plane]);
660*bbecb9d1SAndroid Build Coastguard Worker       if (ret < 0) {
661*bbecb9d1SAndroid Build Coastguard Worker          vrend_printf( "failed to export plane handle\n");
662*bbecb9d1SAndroid Build Coastguard Worker          goto out_close;
663*bbecb9d1SAndroid Build Coastguard Worker       }
664*bbecb9d1SAndroid Build Coastguard Worker 
665*bbecb9d1SAndroid Build Coastguard Worker       strides[plane] = gbm_bo_get_stride_for_plane(bo, plane);
666*bbecb9d1SAndroid Build Coastguard Worker       offsets[plane] = gbm_bo_get_offset(bo, plane);
667*bbecb9d1SAndroid Build Coastguard Worker    }
668*bbecb9d1SAndroid Build Coastguard Worker 
669*bbecb9d1SAndroid Build Coastguard Worker    image = virgl_egl_image_from_dmabuf(egl,
670*bbecb9d1SAndroid Build Coastguard Worker                                        gbm_bo_get_width(bo),
671*bbecb9d1SAndroid Build Coastguard Worker                                        gbm_bo_get_height(bo),
672*bbecb9d1SAndroid Build Coastguard Worker                                        gbm_bo_get_format(bo),
673*bbecb9d1SAndroid Build Coastguard Worker                                        gbm_bo_get_modifier(bo),
674*bbecb9d1SAndroid Build Coastguard Worker                                        num_planes,
675*bbecb9d1SAndroid Build Coastguard Worker                                        fds,
676*bbecb9d1SAndroid Build Coastguard Worker                                        strides,
677*bbecb9d1SAndroid Build Coastguard Worker                                        offsets);
678*bbecb9d1SAndroid Build Coastguard Worker 
679*bbecb9d1SAndroid Build Coastguard Worker out_close:
680*bbecb9d1SAndroid Build Coastguard Worker    for (int plane = 0; plane < num_planes; plane++)
681*bbecb9d1SAndroid Build Coastguard Worker       close(fds[plane]);
682*bbecb9d1SAndroid Build Coastguard Worker 
683*bbecb9d1SAndroid Build Coastguard Worker    return image;
684*bbecb9d1SAndroid Build Coastguard Worker }
685*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_aux_plane_image_from_gbm_bo(struct virgl_egl * egl,struct gbm_bo * bo,int plane)686*bbecb9d1SAndroid Build Coastguard Worker void *virgl_egl_aux_plane_image_from_gbm_bo(struct virgl_egl *egl, struct gbm_bo *bo, int plane)
687*bbecb9d1SAndroid Build Coastguard Worker {
688*bbecb9d1SAndroid Build Coastguard Worker    int ret;
689*bbecb9d1SAndroid Build Coastguard Worker    void *image = NULL;
690*bbecb9d1SAndroid Build Coastguard Worker    int fd = -1;
691*bbecb9d1SAndroid Build Coastguard Worker 
692*bbecb9d1SAndroid Build Coastguard Worker    int bytes_per_pixel = virgl_gbm_get_plane_bytes_per_pixel(bo, plane);
693*bbecb9d1SAndroid Build Coastguard Worker    if (bytes_per_pixel != 1 && bytes_per_pixel != 2)
694*bbecb9d1SAndroid Build Coastguard Worker       return NULL;
695*bbecb9d1SAndroid Build Coastguard Worker 
696*bbecb9d1SAndroid Build Coastguard Worker    uint32_t handle = gbm_bo_get_handle_for_plane(bo, plane).u32;
697*bbecb9d1SAndroid Build Coastguard Worker    ret = drmPrimeHandleToFD(gbm_device_get_fd(egl->gbm->device), handle, DRM_CLOEXEC, &fd);
698*bbecb9d1SAndroid Build Coastguard Worker    if (ret < 0) {
699*bbecb9d1SAndroid Build Coastguard Worker       vrend_printf("failed to export plane handle %d\n", errno);
700*bbecb9d1SAndroid Build Coastguard Worker       return NULL;
701*bbecb9d1SAndroid Build Coastguard Worker    }
702*bbecb9d1SAndroid Build Coastguard Worker 
703*bbecb9d1SAndroid Build Coastguard Worker    const uint32_t format = bytes_per_pixel == 1 ? GBM_FORMAT_R8 : GBM_FORMAT_GR88;
704*bbecb9d1SAndroid Build Coastguard Worker    const uint32_t stride = gbm_bo_get_stride_for_plane(bo, plane);
705*bbecb9d1SAndroid Build Coastguard Worker    const uint32_t offset = gbm_bo_get_offset(bo, plane);
706*bbecb9d1SAndroid Build Coastguard Worker    image = virgl_egl_image_from_dmabuf(egl,
707*bbecb9d1SAndroid Build Coastguard Worker                                        virgl_gbm_get_plane_width(bo, plane),
708*bbecb9d1SAndroid Build Coastguard Worker                                        virgl_gbm_get_plane_height(bo, plane),
709*bbecb9d1SAndroid Build Coastguard Worker                                        format,
710*bbecb9d1SAndroid Build Coastguard Worker                                        gbm_bo_get_modifier(bo),
711*bbecb9d1SAndroid Build Coastguard Worker                                        1,
712*bbecb9d1SAndroid Build Coastguard Worker                                        &fd,
713*bbecb9d1SAndroid Build Coastguard Worker                                        &stride,
714*bbecb9d1SAndroid Build Coastguard Worker                                        &offset);
715*bbecb9d1SAndroid Build Coastguard Worker    close(fd);
716*bbecb9d1SAndroid Build Coastguard Worker 
717*bbecb9d1SAndroid Build Coastguard Worker    return image;
718*bbecb9d1SAndroid Build Coastguard Worker }
719*bbecb9d1SAndroid Build Coastguard Worker #endif /* ENABLE_MINIGBM_ALLOCATION */
720*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_supports_fences(struct virgl_egl * egl)721*bbecb9d1SAndroid Build Coastguard Worker bool virgl_egl_supports_fences(struct virgl_egl *egl)
722*bbecb9d1SAndroid Build Coastguard Worker {
723*bbecb9d1SAndroid Build Coastguard Worker    return (egl && has_bit(egl->extension_bits, EGL_KHR_FENCE_SYNC_ANDROID));
724*bbecb9d1SAndroid Build Coastguard Worker }
725*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_fence_create(struct virgl_egl * egl)726*bbecb9d1SAndroid Build Coastguard Worker EGLSyncKHR virgl_egl_fence_create(struct virgl_egl *egl)
727*bbecb9d1SAndroid Build Coastguard Worker {
728*bbecb9d1SAndroid Build Coastguard Worker    if (!egl || !has_bit(egl->extension_bits, EGL_KHR_FENCE_SYNC_ANDROID)) {
729*bbecb9d1SAndroid Build Coastguard Worker       return EGL_NO_SYNC_KHR;
730*bbecb9d1SAndroid Build Coastguard Worker    }
731*bbecb9d1SAndroid Build Coastguard Worker 
732*bbecb9d1SAndroid Build Coastguard Worker    return eglCreateSyncKHR(egl->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
733*bbecb9d1SAndroid Build Coastguard Worker }
734*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_fence_destroy(struct virgl_egl * egl,EGLSyncKHR fence)735*bbecb9d1SAndroid Build Coastguard Worker void virgl_egl_fence_destroy(struct virgl_egl *egl, EGLSyncKHR fence) {
736*bbecb9d1SAndroid Build Coastguard Worker    eglDestroySyncKHR(egl->egl_display, fence);
737*bbecb9d1SAndroid Build Coastguard Worker }
738*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_client_wait_fence(struct virgl_egl * egl,EGLSyncKHR fence,bool blocking)739*bbecb9d1SAndroid Build Coastguard Worker bool virgl_egl_client_wait_fence(struct virgl_egl *egl, EGLSyncKHR fence, bool blocking)
740*bbecb9d1SAndroid Build Coastguard Worker {
741*bbecb9d1SAndroid Build Coastguard Worker    /* attempt to poll the native fence fd instead of eglClientWaitSyncKHR() to
742*bbecb9d1SAndroid Build Coastguard Worker     * avoid Mesa's eglapi global-display-lock synchronizing vrend's sync_thread.
743*bbecb9d1SAndroid Build Coastguard Worker     */
744*bbecb9d1SAndroid Build Coastguard Worker    int fd = -1;
745*bbecb9d1SAndroid Build Coastguard Worker    if (!virgl_egl_export_fence(egl, fence, &fd)) {
746*bbecb9d1SAndroid Build Coastguard Worker       EGLint egl_result = eglClientWaitSyncKHR(egl->egl_display, fence, 0,
747*bbecb9d1SAndroid Build Coastguard Worker                                                blocking ? EGL_FOREVER_KHR : 0);
748*bbecb9d1SAndroid Build Coastguard Worker       if (egl_result == EGL_FALSE)
749*bbecb9d1SAndroid Build Coastguard Worker          vrend_printf("wait sync failed\n");
750*bbecb9d1SAndroid Build Coastguard Worker       return egl_result != EGL_TIMEOUT_EXPIRED_KHR;
751*bbecb9d1SAndroid Build Coastguard Worker    }
752*bbecb9d1SAndroid Build Coastguard Worker    assert(fd >= 0);
753*bbecb9d1SAndroid Build Coastguard Worker 
754*bbecb9d1SAndroid Build Coastguard Worker    int ret;
755*bbecb9d1SAndroid Build Coastguard Worker    struct pollfd pfd = {
756*bbecb9d1SAndroid Build Coastguard Worker       .fd = fd,
757*bbecb9d1SAndroid Build Coastguard Worker       .events = POLLIN,
758*bbecb9d1SAndroid Build Coastguard Worker    };
759*bbecb9d1SAndroid Build Coastguard Worker    do {
760*bbecb9d1SAndroid Build Coastguard Worker       ret = poll(&pfd, 1, blocking ? -1 : 0);
761*bbecb9d1SAndroid Build Coastguard Worker       if (ret > 0 && (pfd.revents & (POLLERR | POLLNVAL))) {
762*bbecb9d1SAndroid Build Coastguard Worker          ret = -1;
763*bbecb9d1SAndroid Build Coastguard Worker          break;
764*bbecb9d1SAndroid Build Coastguard Worker       }
765*bbecb9d1SAndroid Build Coastguard Worker    } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
766*bbecb9d1SAndroid Build Coastguard Worker    close(fd);
767*bbecb9d1SAndroid Build Coastguard Worker 
768*bbecb9d1SAndroid Build Coastguard Worker    if (ret < 0)
769*bbecb9d1SAndroid Build Coastguard Worker       vrend_printf("wait sync failed\n");
770*bbecb9d1SAndroid Build Coastguard Worker    return ret != 0;
771*bbecb9d1SAndroid Build Coastguard Worker }
772*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_export_signaled_fence(struct virgl_egl * egl,int * out_fd)773*bbecb9d1SAndroid Build Coastguard Worker bool virgl_egl_export_signaled_fence(struct virgl_egl *egl, int *out_fd) {
774*bbecb9d1SAndroid Build Coastguard Worker    return virgl_egl_export_fence(egl, egl->signaled_fence, out_fd);
775*bbecb9d1SAndroid Build Coastguard Worker }
776*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_export_fence(struct virgl_egl * egl,EGLSyncKHR fence,int * out_fd)777*bbecb9d1SAndroid Build Coastguard Worker bool virgl_egl_export_fence(struct virgl_egl *egl, EGLSyncKHR fence, int *out_fd) {
778*bbecb9d1SAndroid Build Coastguard Worker    *out_fd = eglDupNativeFenceFDANDROID(egl->egl_display, fence);
779*bbecb9d1SAndroid Build Coastguard Worker    return *out_fd != EGL_NO_NATIVE_FENCE_FD_ANDROID;
780*bbecb9d1SAndroid Build Coastguard Worker }
781*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_different_gpu(struct virgl_egl * egl)782*bbecb9d1SAndroid Build Coastguard Worker bool virgl_egl_different_gpu(struct virgl_egl *egl)
783*bbecb9d1SAndroid Build Coastguard Worker {
784*bbecb9d1SAndroid Build Coastguard Worker    return egl->different_gpu;
785*bbecb9d1SAndroid Build Coastguard Worker }
786*bbecb9d1SAndroid Build Coastguard Worker 
virgl_egl_error_string(EGLint error)787*bbecb9d1SAndroid Build Coastguard Worker const char *virgl_egl_error_string(EGLint error)
788*bbecb9d1SAndroid Build Coastguard Worker {
789*bbecb9d1SAndroid Build Coastguard Worker     switch (error) {
790*bbecb9d1SAndroid Build Coastguard Worker #define CASE_STR( value ) case value: return #value;
791*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_SUCCESS             )
792*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_NOT_INITIALIZED     )
793*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_ACCESS          )
794*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_ALLOC           )
795*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_ATTRIBUTE       )
796*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_CONTEXT         )
797*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_CONFIG          )
798*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_CURRENT_SURFACE )
799*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_DISPLAY         )
800*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_SURFACE         )
801*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_MATCH           )
802*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_PARAMETER       )
803*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_NATIVE_PIXMAP   )
804*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_BAD_NATIVE_WINDOW   )
805*bbecb9d1SAndroid Build Coastguard Worker     CASE_STR( EGL_CONTEXT_LOST        )
806*bbecb9d1SAndroid Build Coastguard Worker #undef CASE_STR
807*bbecb9d1SAndroid Build Coastguard Worker     default: return "Unknown error";
808*bbecb9d1SAndroid Build Coastguard Worker     }
809*bbecb9d1SAndroid Build Coastguard Worker }
810