xref: /OK3568_Linux_fs/external/libmali/hook/hook.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *  Copyright (c) 2020, Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  *  This program is free software; you can redistribute it and/or modify
5*4882a593Smuzhiyun  *  it under the terms of the GNU General Public License as published by
6*4882a593Smuzhiyun  *  the Free Software Foundation; either version 2 of the License, or
7*4882a593Smuzhiyun  *  (at your option) any later version.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  *  This program is distributed in the hope that it will be useful,
10*4882a593Smuzhiyun  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11*4882a593Smuzhiyun  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*4882a593Smuzhiyun  *  GNU General Public License for more details.
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #ifndef _GNU_SOURCE
16*4882a593Smuzhiyun #define _GNU_SOURCE 1
17*4882a593Smuzhiyun #endif
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <dlfcn.h>
20*4882a593Smuzhiyun #include <errno.h>
21*4882a593Smuzhiyun #include <fcntl.h>
22*4882a593Smuzhiyun #include <stdio.h>
23*4882a593Smuzhiyun #include <stdlib.h>
24*4882a593Smuzhiyun #include <stdbool.h>
25*4882a593Smuzhiyun #include <string.h>
26*4882a593Smuzhiyun #include <xf86drm.h>
27*4882a593Smuzhiyun #include <sys/mman.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #ifdef HAS_GBM
30*4882a593Smuzhiyun #include <gbm.h>
31*4882a593Smuzhiyun #endif
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #ifdef HAS_EGL
34*4882a593Smuzhiyun #include <EGL/egl.h>
35*4882a593Smuzhiyun #include <EGL/eglext.h>
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #ifdef HAS_X11
39*4882a593Smuzhiyun #include <pthread.h>
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #include <X11/Xlib.h>
42*4882a593Smuzhiyun #include <X11/Xlibint.h>
43*4882a593Smuzhiyun #endif
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #ifndef ARRAY_SIZE
46*4882a593Smuzhiyun #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
47*4882a593Smuzhiyun #endif
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #ifndef DRM_FORMAT_MOD_LINEAR
50*4882a593Smuzhiyun #define DRM_FORMAT_MOD_LINEAR 0
51*4882a593Smuzhiyun #endif
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #ifndef DRM_FORMAT_MOD_INVALID
54*4882a593Smuzhiyun #define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
55*4882a593Smuzhiyun #endif
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /* A stub symbol to ensure that the hook library would not be removed as unused */
58*4882a593Smuzhiyun int mali_injected = 0;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /* Override libmali symbols */
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #ifdef HAS_GBM
63*4882a593Smuzhiyun static struct gbm_surface * (* _gbm_surface_create)(struct gbm_device *, uint32_t, uint32_t, uint32_t, uint32_t) = NULL;
64*4882a593Smuzhiyun static struct gbm_bo * (* _gbm_bo_create) (struct gbm_device *, uint32_t, uint32_t, uint32_t, uint32_t) = NULL;
65*4882a593Smuzhiyun #ifdef HAS_gbm_bo_get_modifier
66*4882a593Smuzhiyun static uint64_t (* _gbm_bo_get_modifier) (struct gbm_bo *bo) = NULL;
67*4882a593Smuzhiyun #endif
68*4882a593Smuzhiyun #endif
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun #ifdef HAS_EGL
71*4882a593Smuzhiyun static PFNEGLGETDISPLAYPROC _eglGetDisplay = NULL;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun #ifdef HAS_X11
74*4882a593Smuzhiyun static PFNEGLGETPROCADDRESSPROC _eglGetProcAddress = NULL;
75*4882a593Smuzhiyun static PFNEGLGETPLATFORMDISPLAYPROC _eglGetPlatformDisplay = NULL;
76*4882a593Smuzhiyun static PFNEGLGETPLATFORMDISPLAYEXTPROC _eglGetPlatformDisplayEXT = NULL;
77*4882a593Smuzhiyun #endif
78*4882a593Smuzhiyun #endif
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun #define MALI_SYMBOL(func) { #func, (void **)(&_ ## func), }
81*4882a593Smuzhiyun static struct {
82*4882a593Smuzhiyun    const char *func;
83*4882a593Smuzhiyun    void **symbol;
84*4882a593Smuzhiyun } mali_symbols[] = {
85*4882a593Smuzhiyun #ifdef HAS_GBM
86*4882a593Smuzhiyun    MALI_SYMBOL(gbm_surface_create),
87*4882a593Smuzhiyun    MALI_SYMBOL(gbm_bo_create),
88*4882a593Smuzhiyun #ifdef HAS_gbm_bo_get_modifier
89*4882a593Smuzhiyun    MALI_SYMBOL(gbm_bo_get_modifier),
90*4882a593Smuzhiyun #endif
91*4882a593Smuzhiyun #endif
92*4882a593Smuzhiyun #ifdef HAS_EGL
93*4882a593Smuzhiyun    MALI_SYMBOL(eglGetDisplay),
94*4882a593Smuzhiyun #ifdef HAS_X11
95*4882a593Smuzhiyun    MALI_SYMBOL(eglGetProcAddress),
96*4882a593Smuzhiyun #endif
97*4882a593Smuzhiyun #endif
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun __attribute__((constructor)) static void
load_mali_symbols(void)101*4882a593Smuzhiyun load_mali_symbols(void)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun    void *handle, *symbol;
104*4882a593Smuzhiyun    int i;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun    /* The libmali should be already loaded */
107*4882a593Smuzhiyun    handle = dlopen(LIBMALI_SO, RTLD_LAZY | RTLD_NOLOAD);
108*4882a593Smuzhiyun    if (!handle) {
109*4882a593Smuzhiyun       /* Should not reach here */
110*4882a593Smuzhiyun       fprintf(stderr, "FATAL: dlopen(" LIBMALI_SO ") failed(%s)\n", dlerror());
111*4882a593Smuzhiyun       exit(-1);
112*4882a593Smuzhiyun    }
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun    for (i = 0; i < ARRAY_SIZE(mali_symbols); i++) {
115*4882a593Smuzhiyun       const char *func = mali_symbols[i].func;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun       /* Clear error */
118*4882a593Smuzhiyun       dlerror();
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun       symbol = dlsym(handle, func);
121*4882a593Smuzhiyun       if (!symbol) {
122*4882a593Smuzhiyun          /* Should not reach here */
123*4882a593Smuzhiyun          fprintf(stderr, "FATAL: " LIBMALI_SO " dlsym(%s) failed(%s)\n",
124*4882a593Smuzhiyun                  func, dlerror());
125*4882a593Smuzhiyun          exit(-1);
126*4882a593Smuzhiyun       }
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun       *mali_symbols[i].symbol = symbol;
129*4882a593Smuzhiyun    }
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun    dlclose(handle);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun #ifdef HAS_EGL
134*4882a593Smuzhiyun #ifdef HAS_X11
135*4882a593Smuzhiyun    _eglGetPlatformDisplay =
136*4882a593Smuzhiyun       (PFNEGLGETPLATFORMDISPLAYPROC)_eglGetProcAddress("eglGetPlatformDisplay");
137*4882a593Smuzhiyun    _eglGetPlatformDisplayEXT =
138*4882a593Smuzhiyun       (PFNEGLGETPLATFORMDISPLAYEXTPROC)_eglGetProcAddress("eglGetPlatformDisplayEXT");
139*4882a593Smuzhiyun #endif
140*4882a593Smuzhiyun #endif
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun #ifdef HAS_GBM
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun /* Implement new GBM APIs */
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun __attribute__((unused)) static inline bool
can_ignore_modifiers(const uint64_t * modifiers,const unsigned int count)148*4882a593Smuzhiyun can_ignore_modifiers(const uint64_t *modifiers,
149*4882a593Smuzhiyun                      const unsigned int count)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun    for (int i = 0; i < count; i++) {
152*4882a593Smuzhiyun       /* linear or invalid */
153*4882a593Smuzhiyun       if (!modifiers[i] || modifiers[i] == DRM_FORMAT_MOD_INVALID) {
154*4882a593Smuzhiyun          return true;
155*4882a593Smuzhiyun       }
156*4882a593Smuzhiyun    }
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun    return !count;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun #ifndef HAS_gbm_bo_get_offset
162*4882a593Smuzhiyun uint32_t
gbm_bo_get_offset(struct gbm_bo * bo,int plane)163*4882a593Smuzhiyun gbm_bo_get_offset(struct gbm_bo *bo, int plane)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun    return 0;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun #endif
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun #ifndef HAS_gbm_bo_get_plane_count
170*4882a593Smuzhiyun int
gbm_bo_get_plane_count(struct gbm_bo * bo)171*4882a593Smuzhiyun gbm_bo_get_plane_count(struct gbm_bo *bo)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun    return 1;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun #endif
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun #ifndef HAS_gbm_bo_get_stride_for_plane
178*4882a593Smuzhiyun uint32_t
gbm_bo_get_stride_for_plane(struct gbm_bo * bo,int plane)179*4882a593Smuzhiyun gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun    if (plane)
182*4882a593Smuzhiyun       return 0;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun    return gbm_bo_get_stride(bo);
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun #endif
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun #ifndef HAS_gbm_bo_get_fd_for_plane
189*4882a593Smuzhiyun int
gbm_bo_get_fd_for_plane(struct gbm_bo * bo,int plane)190*4882a593Smuzhiyun gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun    if (plane)
193*4882a593Smuzhiyun       return -1;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun    return gbm_bo_get_fd(bo);
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun #endif
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun #ifndef HAS_gbm_bo_get_handle_for_plane
200*4882a593Smuzhiyun union gbm_bo_handle
gbm_bo_get_handle_for_plane(struct gbm_bo * bo,int plane)201*4882a593Smuzhiyun gbm_bo_get_handle_for_plane(struct gbm_bo *bo, int plane)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun    union gbm_bo_handle ret;
204*4882a593Smuzhiyun    ret.s32 = -1;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun    if (plane)
207*4882a593Smuzhiyun       return ret;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun    return gbm_bo_get_handle(bo);
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun #endif
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun #ifndef HAS_gbm_device_get_format_modifier_plane_count
214*4882a593Smuzhiyun int
gbm_device_get_format_modifier_plane_count(struct gbm_device * gbm,uint32_t format,uint64_t modifier)215*4882a593Smuzhiyun gbm_device_get_format_modifier_plane_count(struct gbm_device *gbm,
216*4882a593Smuzhiyun                                            uint32_t format,
217*4882a593Smuzhiyun                                            uint64_t modifier)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun    return can_ignore_modifiers(&modifier, 1) ? 1 : 0;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun #endif
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun #ifndef HAS_gbm_bo_create_with_modifiers
224*4882a593Smuzhiyun struct gbm_bo *
gbm_bo_create_with_modifiers(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,const uint64_t * modifiers,const unsigned int count)225*4882a593Smuzhiyun gbm_bo_create_with_modifiers(struct gbm_device *gbm,
226*4882a593Smuzhiyun                              uint32_t width, uint32_t height,
227*4882a593Smuzhiyun                              uint32_t format,
228*4882a593Smuzhiyun                              const uint64_t *modifiers,
229*4882a593Smuzhiyun                              const unsigned int count)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun    if (!can_ignore_modifiers(modifiers, count))
232*4882a593Smuzhiyun       return NULL;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun    return gbm_bo_create(gbm, width, height, format, GBM_BO_USE_LINEAR);
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun #endif
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun #ifndef HAS_gbm_surface_create_with_modifiers
239*4882a593Smuzhiyun struct gbm_surface *
gbm_surface_create_with_modifiers(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,const uint64_t * modifiers,const unsigned int count)240*4882a593Smuzhiyun gbm_surface_create_with_modifiers(struct gbm_device *gbm,
241*4882a593Smuzhiyun                                   uint32_t width, uint32_t height,
242*4882a593Smuzhiyun                                   uint32_t format,
243*4882a593Smuzhiyun                                   const uint64_t *modifiers,
244*4882a593Smuzhiyun                                   const unsigned int count)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun    if (!can_ignore_modifiers(modifiers, count))
247*4882a593Smuzhiyun       return NULL;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun    return gbm_surface_create(gbm, width, height, format, 0);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun #endif
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun #ifndef HAS_gbm_bo_map
254*4882a593Smuzhiyun void *
gbm_bo_map(struct gbm_bo * bo,uint32_t x,uint32_t y,uint32_t width,uint32_t height,uint32_t flags,uint32_t * stride,void ** map_data)255*4882a593Smuzhiyun gbm_bo_map(struct gbm_bo *bo,
256*4882a593Smuzhiyun            uint32_t x, uint32_t y, uint32_t width, uint32_t height,
257*4882a593Smuzhiyun            uint32_t flags, uint32_t *stride, void **map_data)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun    struct drm_mode_map_dumb arg;
260*4882a593Smuzhiyun    struct gbm_device *gbm_dev;
261*4882a593Smuzhiyun    void *map;
262*4882a593Smuzhiyun    int fd, ret;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun    if (!bo || !map_data || width <= 0 || width > gbm_bo_get_width(bo) ||
265*4882a593Smuzhiyun        height <= 0 || height > gbm_bo_get_height(bo)) {
266*4882a593Smuzhiyun       errno = EINVAL;
267*4882a593Smuzhiyun       return MAP_FAILED;
268*4882a593Smuzhiyun    }
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun    gbm_dev = gbm_bo_get_device(bo);
271*4882a593Smuzhiyun    if (!gbm_dev)
272*4882a593Smuzhiyun       return MAP_FAILED;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun    fd = gbm_device_get_fd(gbm_dev);
275*4882a593Smuzhiyun    if (fd < 0)
276*4882a593Smuzhiyun       return MAP_FAILED;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun    memset(&arg, 0, sizeof(arg));
279*4882a593Smuzhiyun    arg.handle = gbm_bo_get_handle(bo).u32;
280*4882a593Smuzhiyun    ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
281*4882a593Smuzhiyun    if (ret)
282*4882a593Smuzhiyun       return MAP_FAILED;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun    map = mmap(NULL, gbm_bo_get_stride(bo) * gbm_bo_get_height(bo),
285*4882a593Smuzhiyun               PROT_READ | PROT_WRITE, MAP_SHARED, fd, arg.offset);
286*4882a593Smuzhiyun    if (map == MAP_FAILED)
287*4882a593Smuzhiyun       return map;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun    *map_data = map;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun    if (stride)
292*4882a593Smuzhiyun       *stride = gbm_bo_get_stride(bo);
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun    return map + y * gbm_bo_get_stride(bo) + x * (gbm_bo_get_bpp(bo) >> 3);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun #endif
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun #ifndef HAS_gbm_bo_unmap
299*4882a593Smuzhiyun void
gbm_bo_unmap(struct gbm_bo * bo,void * map_data)300*4882a593Smuzhiyun gbm_bo_unmap(struct gbm_bo *bo, void *map_data)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun    if (map_data)
303*4882a593Smuzhiyun       munmap(map_data, gbm_bo_get_stride(bo) * gbm_bo_get_height(bo));
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun #endif
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun /* From mesa3d 20.1.5 : src/gbm/main/gbm.c */
308*4882a593Smuzhiyun #ifndef HAS_gbm_bo_get_bpp
309*4882a593Smuzhiyun uint32_t
gbm_bo_get_bpp(struct gbm_bo * bo)310*4882a593Smuzhiyun gbm_bo_get_bpp(struct gbm_bo *bo)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun    switch (gbm_bo_get_format(bo)) {
313*4882a593Smuzhiyun    default:
314*4882a593Smuzhiyun       return 0;
315*4882a593Smuzhiyun    case GBM_FORMAT_C8:
316*4882a593Smuzhiyun    case GBM_FORMAT_R8:
317*4882a593Smuzhiyun    case GBM_FORMAT_RGB332:
318*4882a593Smuzhiyun    case GBM_FORMAT_BGR233:
319*4882a593Smuzhiyun       return 8;
320*4882a593Smuzhiyun    case GBM_FORMAT_GR88:
321*4882a593Smuzhiyun    case GBM_FORMAT_XRGB4444:
322*4882a593Smuzhiyun    case GBM_FORMAT_XBGR4444:
323*4882a593Smuzhiyun    case GBM_FORMAT_RGBX4444:
324*4882a593Smuzhiyun    case GBM_FORMAT_BGRX4444:
325*4882a593Smuzhiyun    case GBM_FORMAT_ARGB4444:
326*4882a593Smuzhiyun    case GBM_FORMAT_ABGR4444:
327*4882a593Smuzhiyun    case GBM_FORMAT_RGBA4444:
328*4882a593Smuzhiyun    case GBM_FORMAT_BGRA4444:
329*4882a593Smuzhiyun    case GBM_FORMAT_XRGB1555:
330*4882a593Smuzhiyun    case GBM_FORMAT_XBGR1555:
331*4882a593Smuzhiyun    case GBM_FORMAT_RGBX5551:
332*4882a593Smuzhiyun    case GBM_FORMAT_BGRX5551:
333*4882a593Smuzhiyun    case GBM_FORMAT_ARGB1555:
334*4882a593Smuzhiyun    case GBM_FORMAT_ABGR1555:
335*4882a593Smuzhiyun    case GBM_FORMAT_RGBA5551:
336*4882a593Smuzhiyun    case GBM_FORMAT_BGRA5551:
337*4882a593Smuzhiyun    case GBM_FORMAT_RGB565:
338*4882a593Smuzhiyun    case GBM_FORMAT_BGR565:
339*4882a593Smuzhiyun       return 16;
340*4882a593Smuzhiyun    case GBM_FORMAT_RGB888:
341*4882a593Smuzhiyun    case GBM_FORMAT_BGR888:
342*4882a593Smuzhiyun       return 24;
343*4882a593Smuzhiyun    case GBM_FORMAT_XRGB8888:
344*4882a593Smuzhiyun    case GBM_FORMAT_XBGR8888:
345*4882a593Smuzhiyun    case GBM_FORMAT_RGBX8888:
346*4882a593Smuzhiyun    case GBM_FORMAT_BGRX8888:
347*4882a593Smuzhiyun    case GBM_FORMAT_ARGB8888:
348*4882a593Smuzhiyun    case GBM_FORMAT_ABGR8888:
349*4882a593Smuzhiyun    case GBM_FORMAT_RGBA8888:
350*4882a593Smuzhiyun    case GBM_FORMAT_BGRA8888:
351*4882a593Smuzhiyun    case GBM_FORMAT_XRGB2101010:
352*4882a593Smuzhiyun    case GBM_FORMAT_XBGR2101010:
353*4882a593Smuzhiyun    case GBM_FORMAT_RGBX1010102:
354*4882a593Smuzhiyun    case GBM_FORMAT_BGRX1010102:
355*4882a593Smuzhiyun    case GBM_FORMAT_ARGB2101010:
356*4882a593Smuzhiyun    case GBM_FORMAT_ABGR2101010:
357*4882a593Smuzhiyun    case GBM_FORMAT_RGBA1010102:
358*4882a593Smuzhiyun    case GBM_FORMAT_BGRA1010102:
359*4882a593Smuzhiyun       return 32;
360*4882a593Smuzhiyun    case GBM_FORMAT_XBGR16161616F:
361*4882a593Smuzhiyun    case GBM_FORMAT_ABGR16161616F:
362*4882a593Smuzhiyun       return 64;
363*4882a593Smuzhiyun    }
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun #endif
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun /* From mesa3d 20.1.5 : src/gbm/main/gbm.c */
368*4882a593Smuzhiyun #ifndef HAS_gbm_format_get_name
369*4882a593Smuzhiyun static uint32_t
gbm_format_canonicalize(uint32_t gbm_format)370*4882a593Smuzhiyun gbm_format_canonicalize(uint32_t gbm_format)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun    switch (gbm_format) {
373*4882a593Smuzhiyun    case GBM_BO_FORMAT_XRGB8888:
374*4882a593Smuzhiyun       return GBM_FORMAT_XRGB8888;
375*4882a593Smuzhiyun    case GBM_BO_FORMAT_ARGB8888:
376*4882a593Smuzhiyun       return GBM_FORMAT_ARGB8888;
377*4882a593Smuzhiyun    default:
378*4882a593Smuzhiyun       return gbm_format;
379*4882a593Smuzhiyun    }
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun char *
gbm_format_get_name(uint32_t gbm_format,struct gbm_format_name_desc * desc)383*4882a593Smuzhiyun gbm_format_get_name(uint32_t gbm_format, struct gbm_format_name_desc *desc)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun    gbm_format = gbm_format_canonicalize(gbm_format);
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun    desc->name[0] = gbm_format;
388*4882a593Smuzhiyun    desc->name[1] = gbm_format >> 8;
389*4882a593Smuzhiyun    desc->name[2] = gbm_format >> 16;
390*4882a593Smuzhiyun    desc->name[3] = gbm_format >> 24;
391*4882a593Smuzhiyun    desc->name[4] = 0;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun    return desc->name;
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun #endif
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun /* Wrappers for invalid modifier */
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun uint64_t
gbm_bo_get_modifier(struct gbm_bo * bo)400*4882a593Smuzhiyun gbm_bo_get_modifier(struct gbm_bo *bo)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun #ifdef HAS_gbm_bo_get_modifier
403*4882a593Smuzhiyun    uint64_t modifier = _gbm_bo_get_modifier(bo);
404*4882a593Smuzhiyun    if (modifier != DRM_FORMAT_MOD_INVALID)
405*4882a593Smuzhiyun       return modifier;
406*4882a593Smuzhiyun #endif
407*4882a593Smuzhiyun    return DRM_FORMAT_MOD_LINEAR;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun /* Wrappers for unsupported flags */
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun struct gbm_surface *
gbm_surface_create(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,uint32_t flags)413*4882a593Smuzhiyun gbm_surface_create(struct gbm_device *gbm,
414*4882a593Smuzhiyun                    uint32_t width, uint32_t height,
415*4882a593Smuzhiyun                    uint32_t format, uint32_t flags)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun    struct gbm_surface *surface;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun    surface = _gbm_surface_create(gbm, width, height, format, flags);
420*4882a593Smuzhiyun    if (surface)
421*4882a593Smuzhiyun       return surface;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun    flags &= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
424*4882a593Smuzhiyun    return _gbm_surface_create(gbm, width, height, format, flags);
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun struct gbm_bo *
gbm_bo_create(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,uint32_t flags)428*4882a593Smuzhiyun gbm_bo_create(struct gbm_device *gbm,
429*4882a593Smuzhiyun               uint32_t width, uint32_t height,
430*4882a593Smuzhiyun               uint32_t format, uint32_t flags)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun    struct gbm_bo *bo;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun    bo = _gbm_bo_create(gbm, width, height, format, flags);
435*4882a593Smuzhiyun    if (bo)
436*4882a593Smuzhiyun       return bo;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun    flags &= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING |
439*4882a593Smuzhiyun       GBM_BO_USE_WRITE | GBM_BO_USE_CURSOR_64X64;
440*4882a593Smuzhiyun    return _gbm_bo_create(gbm, width, height, format, flags);
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun #endif // HAS_GBM
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun #ifdef HAS_EGL
446*4882a593Smuzhiyun #ifdef HAS_X11
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun /* Hacked displays (should not be much) */
449*4882a593Smuzhiyun #define MAX_X11_DISPLAY 32
450*4882a593Smuzhiyun static Display *_x11_displays[MAX_X11_DISPLAY] = { NULL, };
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun static pthread_mutex_t _x11_mutex = PTHREAD_MUTEX_INITIALIZER;
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun static inline int
force_x11_threads(void)455*4882a593Smuzhiyun force_x11_threads(void)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun    return !getenv("MALI_X11_NO_FORCE_THREADS");
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun __attribute__((constructor)) static void
init_x11_threads(void)461*4882a593Smuzhiyun init_x11_threads(void)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun    if (force_x11_threads())
464*4882a593Smuzhiyun       XInitThreads();
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun __attribute__((destructor)) static void
cleanup_x11_display(void)468*4882a593Smuzhiyun cleanup_x11_display(void)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun    int i;
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun    for (i = 0; i < MAX_X11_DISPLAY; i++) {
473*4882a593Smuzhiyun       Display *display = _x11_displays[i];
474*4882a593Smuzhiyun       if (display)
475*4882a593Smuzhiyun          XCloseDisplay(display);
476*4882a593Smuzhiyun    }
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun static Display *
fixup_x11_display(Display * display)480*4882a593Smuzhiyun fixup_x11_display(Display *display)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun    int i;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun    if (!force_x11_threads())
485*4882a593Smuzhiyun       return display;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun    if (!display || display->lock_fns)
488*4882a593Smuzhiyun       return display;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun    pthread_mutex_lock(&_x11_mutex);
491*4882a593Smuzhiyun    /* Create a new threaded display */
492*4882a593Smuzhiyun    display = XOpenDisplay(DisplayString(display));
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun    for (i = 0; i < MAX_X11_DISPLAY; i++) {
495*4882a593Smuzhiyun       if (!_x11_displays[i]) {
496*4882a593Smuzhiyun          _x11_displays[i] = display;
497*4882a593Smuzhiyun          break;
498*4882a593Smuzhiyun       }
499*4882a593Smuzhiyun    }
500*4882a593Smuzhiyun    pthread_mutex_unlock(&_x11_mutex);
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun    return display;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun /* Override EGL symbols */
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun EGLAPI EGLDisplay EGLAPIENTRY
eglGetPlatformDisplay(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)508*4882a593Smuzhiyun eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun    if (!_eglGetPlatformDisplay)
511*4882a593Smuzhiyun       return EGL_NO_DISPLAY;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun    if (platform == EGL_PLATFORM_X11_KHR && native_display) {
514*4882a593Smuzhiyun       native_display = (void *)fixup_x11_display(native_display);
515*4882a593Smuzhiyun       if (!native_display)
516*4882a593Smuzhiyun          return EGL_NO_DISPLAY;
517*4882a593Smuzhiyun    }
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun    return _eglGetPlatformDisplay(platform, native_display, attrib_list);
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun EGLAPI EGLDisplay EGLAPIENTRY
eglGetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * attrib_list)523*4882a593Smuzhiyun eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun    if (!_eglGetPlatformDisplayEXT)
526*4882a593Smuzhiyun       return EGL_NO_DISPLAY;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun    if (platform == EGL_PLATFORM_X11_KHR && native_display) {
529*4882a593Smuzhiyun       native_display = (void *)fixup_x11_display(native_display);
530*4882a593Smuzhiyun       if (!native_display)
531*4882a593Smuzhiyun          return EGL_NO_DISPLAY;
532*4882a593Smuzhiyun    }
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun    return _eglGetPlatformDisplayEXT(platform, native_display, attrib_list);
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
eglGetProcAddress(const char * procname)538*4882a593Smuzhiyun eglGetProcAddress(const char *procname)
539*4882a593Smuzhiyun {
540*4882a593Smuzhiyun    if (!procname)
541*4882a593Smuzhiyun       return NULL;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun    if (!strcmp(procname, __func__))
544*4882a593Smuzhiyun       return (__eglMustCastToProperFunctionPointerType)eglGetProcAddress;
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun    if (!strcmp(procname, "eglGetDisplay"))
547*4882a593Smuzhiyun       return (__eglMustCastToProperFunctionPointerType)eglGetDisplay;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun    if (!strcmp(procname, "eglGetPlatformDisplay")) {
550*4882a593Smuzhiyun       if (!_eglGetPlatformDisplay)
551*4882a593Smuzhiyun          return NULL;
552*4882a593Smuzhiyun       return (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplay;
553*4882a593Smuzhiyun    }
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun    if (!strcmp(procname, "eglGetPlatformDisplayEXT")) {
556*4882a593Smuzhiyun       if (!_eglGetPlatformDisplayEXT)
557*4882a593Smuzhiyun          return NULL;
558*4882a593Smuzhiyun       return (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplayEXT;
559*4882a593Smuzhiyun    }
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun    return _eglGetProcAddress(procname);
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun #endif // HAS_X11
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun EGLAPI EGLDisplay EGLAPIENTRY
eglGetDisplay(EGLNativeDisplayType display_id)567*4882a593Smuzhiyun eglGetDisplay (EGLNativeDisplayType display_id)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun     const char *type = getenv("MALI_DEFAULT_WINSYS");
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun     static PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = NULL;
572*4882a593Smuzhiyun     if (!get_platform_display)
573*4882a593Smuzhiyun         get_platform_display = (PFNEGLGETPLATFORMDISPLAYEXTPROC)
574*4882a593Smuzhiyun             eglGetProcAddress("eglGetPlatformDisplayEXT");
575*4882a593Smuzhiyun     if (!get_platform_display)
576*4882a593Smuzhiyun         goto bail;
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun #ifdef HAS_GBM
579*4882a593Smuzhiyun     if (type && !strcmp(type, "gbm"))
580*4882a593Smuzhiyun         return get_platform_display(EGL_PLATFORM_GBM_KHR, display_id, NULL);
581*4882a593Smuzhiyun #endif
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun #ifdef HAS_WAYLAND
584*4882a593Smuzhiyun     if (type && !strcmp(type, "wayland"))
585*4882a593Smuzhiyun         return get_platform_display(EGL_PLATFORM_WAYLAND_EXT, display_id, NULL);
586*4882a593Smuzhiyun #endif
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun #ifdef HAS_X11
589*4882a593Smuzhiyun     /* Use X11 by default when avaiable */
590*4882a593Smuzhiyun     return get_platform_display(EGL_PLATFORM_X11_KHR, display_id, NULL);
591*4882a593Smuzhiyun #endif
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun bail:
594*4882a593Smuzhiyun     return _eglGetDisplay(display_id);
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun #endif // HAS_EGL
598