1 /*
2 * Copyright 2024 Red Hat, Inc.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 /*
8 * Compatibility stub for Xorg. This responds to just enough of the legacy DRI
9 * interface to allow the X server to initialize GLX and enable direct
10 * rendering clients. It implements the screen creation hook and provides a
11 * (static, unambitious) list of framebuffer configs. It will not create an
12 * indirect context; Indirect contexts have been disabled by default since
13 * 2014 and would be limited to GL 1.4 in any case, so this is no great loss.
14 *
15 * If you do want indirect contexts to work, you have options. This stub is
16 * new with Mesa 24.1, so one option is to use an older Mesa release stream.
17 * Another option is to use an X server that does not need this interface. For
18 * Xwayland and Xephyr that's XX.X or newer, and for Xorg drivers using glamor
19 * for acceleration that's YY.Y or newer.
20 */
21
22 #include "main/glconfig.h"
23 #include "main/mtypes.h"
24 #include <GL/internal/dri_interface.h>
25 #include <dlfcn.h>
26 #include <EGL/egl.h>
27 #include <EGL/eglext.h>
28 #include "gbm/main/gbm.h"
29 #include "drm-uapi/drm_fourcc.h"
30
31 #define EGL_PLATFORM_GBM_MESA 0x31D7
32
33 /* avoid needing X11 headers */
34 #define GLX_NONE 0x8000
35 #define GLX_DONT_CARE 0xFFFFFFFF
36
37 #define CONFIG_ZS(color, zs) \
38 { \
39 .color_format = color, \
40 .zs_format = zs, \
41 }
42
43 #define CONFIG(color) \
44 CONFIG_ZS(color, PIPE_FORMAT_S8_UINT), \
45 CONFIG_ZS(color, PIPE_FORMAT_Z24_UNORM_S8_UINT), \
46 CONFIG_ZS(color, PIPE_FORMAT_Z24X8_UNORM), \
47 CONFIG_ZS(color, PIPE_FORMAT_Z16_UNORM), \
48 CONFIG_ZS(color, PIPE_FORMAT_NONE) \
49
50 static const struct gl_config drilConfigs[] = {
51 CONFIG(PIPE_FORMAT_R8G8B8A8_UNORM),
52 CONFIG(PIPE_FORMAT_R8G8B8X8_UNORM),
53 CONFIG(PIPE_FORMAT_B8G8R8A8_UNORM),
54 CONFIG(PIPE_FORMAT_B8G8R8X8_UNORM),
55 CONFIG(PIPE_FORMAT_R10G10B10A2_UNORM),
56 CONFIG(PIPE_FORMAT_R10G10B10X2_UNORM),
57 CONFIG(PIPE_FORMAT_B10G10R10A2_UNORM),
58 CONFIG(PIPE_FORMAT_B10G10R10X2_UNORM),
59 CONFIG(PIPE_FORMAT_R5G6B5_UNORM),
60 CONFIG(PIPE_FORMAT_R5G5B5A1_UNORM),
61 CONFIG(PIPE_FORMAT_R5G5B5X1_UNORM),
62 CONFIG(PIPE_FORMAT_R4G4B4A4_UNORM),
63 CONFIG(PIPE_FORMAT_R4G4B4X4_UNORM),
64 CONFIG(PIPE_FORMAT_B5G6R5_UNORM),
65 CONFIG(PIPE_FORMAT_B5G5R5A1_UNORM),
66 CONFIG(PIPE_FORMAT_B5G5R5X1_UNORM),
67 CONFIG(PIPE_FORMAT_B4G4R4A4_UNORM),
68 CONFIG(PIPE_FORMAT_B4G4R4X4_UNORM),
69 };
70
71 #define RGB UTIL_FORMAT_COLORSPACE_RGB
72 #define RED 0
73 #define GREEN 1
74 #define BLUE 2
75 #define ALPHA 3
76 #define ZS UTIL_FORMAT_COLORSPACE_ZS
77 #define DEPTH 0
78 #define STENCIL 1
79
80 #define CASE(ATTRIB, VALUE) \
81 case __DRI_ATTRIB_ ## ATTRIB : \
82 *value = VALUE; \
83 break;
84
85 #define SIZE(f, cs, chan) (f ? util_format_get_component_bits(f, cs, chan) : 0)
86 #define SHIFT(f, cs, chan) (f ? util_format_get_component_shift(f, cs, chan) : 0)
87 #define MASK(f, cs, chan) \
88 (((1 << SIZE(f, cs, chan)) - 1) << SHIFT(f, cs, chan))
89
90 static int
drilIndexConfigAttrib(const __DRIconfig * _config,int index,unsigned int * attrib,unsigned int * value)91 drilIndexConfigAttrib(const __DRIconfig *_config, int index,
92 unsigned int *attrib, unsigned int *value)
93 {
94 struct gl_config *config = (void *)_config;
95 enum pipe_format color_format = config->color_format;
96 enum pipe_format zs_format = config->zs_format;
97 enum pipe_format accum_format = config->accum_format;
98
99 if (index >= __DRI_ATTRIB_MAX)
100 return 0;
101
102 switch (index) {
103 case __DRI_ATTRIB_SAMPLE_BUFFERS:
104 *value = !!config->samples;
105 break;
106
107 case __DRI_ATTRIB_BUFFER_SIZE: {
108 unsigned int red = 0, green = 0, blue = 0, alpha = 0;
109 drilIndexConfigAttrib(_config, __DRI_ATTRIB_RED_SIZE, attrib, &red);
110 drilIndexConfigAttrib(_config, __DRI_ATTRIB_GREEN_SIZE, attrib, &green);
111 drilIndexConfigAttrib(_config, __DRI_ATTRIB_BLUE_SIZE, attrib, &blue);
112 drilIndexConfigAttrib(_config, __DRI_ATTRIB_ALPHA_SIZE, attrib, &alpha);
113 *value = red + green + blue + alpha;
114 break;
115 }
116
117 CASE(RED_SIZE, SIZE(color_format, RGB, 0));
118 CASE(GREEN_SIZE, SIZE(color_format, RGB, 1));
119 CASE(BLUE_SIZE, SIZE(color_format, RGB, 2));
120 CASE(ALPHA_SIZE, SIZE(color_format, RGB, 3));
121 CASE(DEPTH_SIZE, SIZE(zs_format, ZS, 0));
122 CASE(STENCIL_SIZE, SIZE(zs_format, ZS, 1));
123 CASE(ACCUM_RED_SIZE, SIZE(accum_format, RGB, 0));
124 CASE(ACCUM_GREEN_SIZE, SIZE(accum_format, RGB, 1));
125 CASE(ACCUM_BLUE_SIZE, SIZE(accum_format, RGB, 2));
126 CASE(ACCUM_ALPHA_SIZE, SIZE(accum_format, RGB, 3));
127
128 CASE(RENDER_TYPE, __DRI_ATTRIB_RGBA_BIT);
129 CASE(CONFORMANT, GL_TRUE);
130 CASE(DOUBLE_BUFFER, config->doubleBufferMode);
131 CASE(SAMPLES, config->samples);
132 CASE(FRAMEBUFFER_SRGB_CAPABLE, config->sRGBCapable);
133
134 CASE(TRANSPARENT_TYPE, GLX_NONE);
135 CASE(TRANSPARENT_INDEX_VALUE, GLX_NONE);
136 CASE(TRANSPARENT_RED_VALUE, GLX_DONT_CARE);
137 CASE(TRANSPARENT_GREEN_VALUE, GLX_DONT_CARE);
138 CASE(TRANSPARENT_BLUE_VALUE, GLX_DONT_CARE);
139 CASE(TRANSPARENT_ALPHA_VALUE, GLX_DONT_CARE);
140
141 CASE(RED_MASK, MASK(color_format, RGB, 0));
142 CASE(GREEN_MASK, MASK(color_format, RGB, 1));
143 CASE(BLUE_MASK, MASK(color_format, RGB, 2));
144 CASE(ALPHA_MASK, MASK(color_format, RGB, 3));
145
146 CASE(SWAP_METHOD, __DRI_ATTRIB_SWAP_UNDEFINED);
147 CASE(MAX_SWAP_INTERVAL, INT_MAX);
148 CASE(BIND_TO_TEXTURE_RGB, GL_TRUE);
149 CASE(BIND_TO_TEXTURE_RGBA, GL_TRUE);
150 CASE(BIND_TO_TEXTURE_TARGETS,
151 __DRI_ATTRIB_TEXTURE_1D_BIT |
152 __DRI_ATTRIB_TEXTURE_2D_BIT |
153 __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT);
154 CASE(YINVERTED, GL_TRUE);
155
156 CASE(RED_SHIFT, SHIFT(color_format, RGB, 0));
157 CASE(GREEN_SHIFT, SHIFT(color_format, RGB, 1));
158 CASE(BLUE_SHIFT, SHIFT(color_format, RGB, 2));
159 CASE(ALPHA_SHIFT, SHIFT(color_format, RGB, 3));
160
161 default:
162 *value = 0;
163 break;
164 }
165
166 *attrib = index;
167 return 1;
168 }
169
170 static void
drilDestroyScreen(__DRIscreen * screen)171 drilDestroyScreen(__DRIscreen *screen)
172 {
173 /* At the moment this is just the bounce table for the configs */
174 free(screen);
175 }
176
177 static const __DRI2flushControlExtension dri2FlushControlExtension = {
178 .base = { __DRI2_FLUSH_CONTROL, 1 }
179 };
180
181 static void
dril_set_tex_buffer2(__DRIcontext * pDRICtx,GLint target,GLint format,__DRIdrawable * dPriv)182 dril_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
183 GLint format, __DRIdrawable *dPriv)
184 {
185 }
186
187 static void
dril_set_tex_buffer(__DRIcontext * pDRICtx,GLint target,__DRIdrawable * dPriv)188 dril_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
189 __DRIdrawable *dPriv)
190 {
191 }
192
193 const __DRItexBufferExtension driTexBufferExtension = {
194 .base = { __DRI_TEX_BUFFER, 2 },
195
196 .setTexBuffer = dril_set_tex_buffer,
197 .setTexBuffer2 = dril_set_tex_buffer2,
198 .releaseTexBuffer = NULL,
199 };
200
201 static const __DRIrobustnessExtension dri2Robustness = {
202 .base = { __DRI2_ROBUSTNESS, 1 }
203 };
204
205 static const __DRIextension *dril_extensions[] = {
206 &dri2FlushControlExtension.base,
207 &driTexBufferExtension.base,
208 &dri2Robustness.base,
209 NULL
210 };
211
212 /* This has to return a pointer to NULL, not just NULL */
213 static const __DRIextension **
drilGetExtensions(__DRIscreen * screen)214 drilGetExtensions(__DRIscreen *screen)
215 {
216 return (void*)&dril_extensions;
217 }
218
219 static __DRIcontext *
drilCreateContextAttribs(__DRIscreen * psp,int api,const __DRIconfig * config,__DRIcontext * shared,unsigned num_attribs,const uint32_t * attribs,unsigned * error,void * data)220 drilCreateContextAttribs(__DRIscreen *psp, int api,
221 const __DRIconfig *config,
222 __DRIcontext *shared,
223 unsigned num_attribs,
224 const uint32_t *attribs,
225 unsigned *error,
226 void *data)
227 {
228 return NULL;
229 }
230
231 static __DRIcontext *
drilCreateNewContextForAPI(__DRIscreen * screen,int api,const __DRIconfig * config,__DRIcontext * shared,void * data)232 drilCreateNewContextForAPI(__DRIscreen *screen, int api,
233 const __DRIconfig *config,
234 __DRIcontext *shared, void *data)
235 {
236 return NULL;
237 }
238
239 static __DRIcontext *
drilCreateNewContext(__DRIscreen * screen,const __DRIconfig * config,__DRIcontext * shared,void * data)240 drilCreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
241 __DRIcontext *shared, void *data)
242 {
243 return NULL;
244 }
245
246 static void
drilDestroyDrawable(__DRIdrawable * pdp)247 drilDestroyDrawable(__DRIdrawable *pdp)
248 {
249 }
250
251 static const __DRIcoreExtension drilCoreExtension = {
252 .base = { __DRI_CORE, 1 },
253
254 .destroyScreen = drilDestroyScreen,
255 .getExtensions = drilGetExtensions,
256 .getConfigAttrib = NULL, // XXX not actually used!
257 .indexConfigAttrib = drilIndexConfigAttrib,
258 .destroyDrawable = drilDestroyDrawable,
259 .createNewContext = drilCreateNewContext,
260 };
261
drilBindContext(__DRIcontext * pcp,__DRIdrawable * pdp,__DRIdrawable * prp)262 static int drilBindContext(__DRIcontext *pcp,
263 __DRIdrawable *pdp,
264 __DRIdrawable *prp)
265 {
266 return 0; // Success
267 }
268
drilUnbindContext(__DRIcontext * pcp)269 static int drilUnbindContext(__DRIcontext *pcp)
270 {
271 return 0; // Success
272 }
273
274 static __DRIdrawable *
drilCreateNewDrawable(__DRIscreen * psp,const __DRIconfig * config,void * data)275 drilCreateNewDrawable(__DRIscreen *psp,
276 const __DRIconfig *config,
277 void *data)
278 {
279 return NULL;
280 }
281
282
283 static enum pipe_format
fourcc_to_pipe_format(int fourcc)284 fourcc_to_pipe_format(int fourcc)
285 {
286 switch (fourcc) {
287 case DRM_FORMAT_RGB565: return PIPE_FORMAT_B5G6R5_UNORM;
288 case DRM_FORMAT_XRGB8888: return PIPE_FORMAT_BGRX8888_UNORM;
289 case DRM_FORMAT_ARGB8888: return PIPE_FORMAT_BGRA8888_UNORM;
290 case DRM_FORMAT_ABGR8888: return PIPE_FORMAT_RGBA8888_UNORM;
291 case DRM_FORMAT_XBGR8888: return PIPE_FORMAT_RGBX8888_UNORM;
292 case DRM_FORMAT_XRGB2101010: return PIPE_FORMAT_B10G10R10X2_UNORM;
293 case DRM_FORMAT_ARGB2101010: return PIPE_FORMAT_B10G10R10A2_UNORM;
294 case DRM_FORMAT_XBGR2101010: return PIPE_FORMAT_R10G10B10X2_UNORM;
295 case DRM_FORMAT_ABGR2101010: return PIPE_FORMAT_R10G10B10A2_UNORM;
296 case DRM_FORMAT_XBGR16161616F: return PIPE_FORMAT_R16G16B16A16_FLOAT;
297 case DRM_FORMAT_ABGR16161616F: return PIPE_FORMAT_R16G16B16X16_FLOAT;
298 case DRM_FORMAT_ARGB1555: return PIPE_FORMAT_B5G5R5A1_UNORM;
299 case DRM_FORMAT_ABGR1555: return PIPE_FORMAT_R5G5B5A1_UNORM;
300 case DRM_FORMAT_ARGB4444: return PIPE_FORMAT_B4G4R4A4_UNORM;
301 case DRM_FORMAT_ABGR4444: return PIPE_FORMAT_R4G4B4A4_UNORM;
302 default: return PIPE_FORMAT_NONE;
303 }
304 }
305
306 static unsigned
add_srgb_config(struct gl_config ** configs,unsigned c,enum pipe_format last_pformat,unsigned last_start)307 add_srgb_config(struct gl_config **configs, unsigned c, enum pipe_format last_pformat, unsigned last_start)
308 {
309 enum pipe_format srgb = util_format_srgb(last_pformat);
310 if (!srgb)
311 return c;
312 unsigned end = c;
313 for (unsigned j = last_start; j < end; j++) {
314 configs[c] = mem_dup(configs[j], sizeof(drilConfigs[j]));
315
316 struct gl_config *cfg = configs[c++];
317 cfg->color_format = srgb;
318 cfg->sRGBCapable = 1;
319 }
320 return c;
321 }
322
323 /* DRI2 awfulness */
324 static const __DRIconfig **
init_dri2_configs(int fd)325 init_dri2_configs(int fd)
326 {
327 void *egl = NULL;
328 struct gl_config **configs = NULL;
329 unsigned c = 0;
330 enum pipe_format last_pformat = 0;
331 unsigned last_start = 0;
332
333 /* dlopen/dlsym to avoid linkage */
334 egl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL);
335 if (!egl)
336 return false;
337
338 void * (*peglGetProcAddress)(const char *) = dlsym(egl, "eglGetProcAddress");
339 EGLDisplay (*peglGetPlatformDisplayEXT)(EGLenum, void *, const EGLint *) = peglGetProcAddress("eglGetPlatformDisplayEXT");
340 EGLBoolean (*peglInitialize)(EGLDisplay, int*, int*) = peglGetProcAddress("eglInitialize");
341 EGLBoolean (*peglTerminate)(EGLDisplay) = peglGetProcAddress("eglTerminate");
342 EGLBoolean (*peglGetConfigs)(EGLDisplay, EGLConfig*, EGLint, EGLint*) = peglGetProcAddress("eglGetConfigs");
343 EGLBoolean (*peglGetConfigAttrib)(EGLDisplay, EGLConfig, EGLint, EGLint *) = peglGetProcAddress("eglGetConfigAttrib");
344 const char *(*peglQueryString)(EGLDisplay, EGLint) = peglGetProcAddress("eglQueryString");
345
346 struct gbm_device *gbm = NULL;
347 if (fd != -1) {
348 /* try opening GBM for hardware driver info */
349 gbm = gbm_create_device(fd);
350 if (!gbm)
351 goto out;
352 }
353
354 EGLDisplay dpy = peglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, gbm ? gbm : EGL_DEFAULT_DISPLAY, NULL);
355 if (!dpy)
356 goto out_gbm;
357 int maj, min;
358 if (!peglInitialize(dpy, &maj, &min))
359 goto out_gbm;
360
361 const char *egl_extension_list = peglQueryString(dpy, EGL_EXTENSIONS);
362 bool has_srgb = strstr(egl_extension_list, "EGL_KHR_gl_colorspace");
363
364 int num_configs = 0;
365 EGLConfig *eglconfigs = NULL;
366 if (!peglGetConfigs(dpy, NULL, 0, &num_configs))
367 goto out_egl;
368 eglconfigs = malloc(sizeof(EGLConfig) * num_configs);
369 /* overestimate: num_configs * doubleBuffer * sRGB + NULL */
370 configs = calloc(num_configs * 2 * 2 + 1, sizeof(struct gl_config));
371 if (!peglGetConfigs(dpy, eglconfigs, num_configs, &num_configs))
372 goto out_egl;
373
374 for (unsigned i = 0; i < num_configs; i++) {
375 /* verify that this is the right format */
376 EGLint format, depth, stencil, samples;
377
378 if (!peglGetConfigAttrib(dpy, eglconfigs[i], EGL_NATIVE_VISUAL_ID, &format) ||
379 !peglGetConfigAttrib(dpy, eglconfigs[i], EGL_DEPTH_SIZE, &depth) ||
380 !peglGetConfigAttrib(dpy, eglconfigs[i], EGL_STENCIL_SIZE, &stencil) ||
381 !peglGetConfigAttrib(dpy, eglconfigs[i], EGL_SAMPLES, &samples))
382 continue;
383
384 enum pipe_format pformat = fourcc_to_pipe_format(format);
385
386 /* srgb configs go after base configs */
387 if (last_pformat && has_srgb && pformat != last_pformat)
388 c = add_srgb_config(configs, c, last_pformat, last_start);
389 /* tracking for the number of srgb configs to create */
390 if (pformat != last_pformat)
391 last_start = c;
392
393 for (unsigned j = 0; j < ARRAY_SIZE(drilConfigs); j++) {
394 unsigned depth_size = SIZE(drilConfigs[j].zs_format, ZS, 0);
395 unsigned stencil_size = SIZE(drilConfigs[j].zs_format, ZS, 1);
396 /* only copy supported configs */
397 if (pformat != drilConfigs[j].color_format || depth != depth_size || stencil != stencil_size)
398 continue;
399
400 /* always create single-buffered and double-buffered */
401 for (unsigned k = 0; k < 2; k++) {
402 configs[c] = mem_dup(&drilConfigs[j], sizeof(drilConfigs[j]));
403
404 struct gl_config *cfg = configs[c++];
405 cfg->samples = samples;
406 cfg->doubleBufferMode = k;
407 }
408 break;
409 }
410 last_pformat = pformat;
411 }
412 /* check last format for srgbness too */
413 if (c && has_srgb)
414 c = add_srgb_config(configs, c, last_pformat, last_start);
415 out_egl:
416 free(eglconfigs);
417 /* don't forget cleanup */
418 peglTerminate(dpy);
419
420 out_gbm:
421 if (gbm)
422 gbm_device_destroy(gbm);
423 out:
424 dlclose(egl);
425 if (c)
426 return (void*)configs;
427 free(configs);
428 return NULL;
429 }
430
431 static __DRIscreen *
drilCreateNewScreen(int scrn,int fd,const __DRIextension ** loader_extensions,const __DRIextension ** driver_extensions,const __DRIconfig *** driver_configs,void * data)432 drilCreateNewScreen(int scrn, int fd,
433 const __DRIextension **loader_extensions,
434 const __DRIextension **driver_extensions,
435 const __DRIconfig ***driver_configs, void *data)
436 {
437 const __DRIconfig **configs = init_dri2_configs(fd);
438 if (!configs && fd == -1) {
439 // otherwise set configs to point to our config list
440 configs = calloc(ARRAY_SIZE(drilConfigs) * 2 + 1, sizeof(void *));
441 int c = 0;
442 for (int i = 0; i < ARRAY_SIZE(drilConfigs); i++) {
443 /* create normal config */
444 configs[c++] = mem_dup(&drilConfigs[i], sizeof(drilConfigs[i]));
445
446 /* create double-buffered config */
447 configs[c] = mem_dup(&drilConfigs[i], sizeof(drilConfigs[i]));
448 struct gl_config *cfg = (void*)configs[c++];
449 cfg->doubleBufferMode = 1;
450 }
451 }
452
453 // outpointer it
454 *driver_configs = configs;
455
456 // This has to be a separate allocation from the configs.
457 // If we had any additional screen state we'd need to do
458 // something less hacky.
459 return malloc(sizeof(int));
460 }
461
462 const __DRIextension *__driDriverExtensions[];
463
464 static __DRIscreen *
dril2CreateNewScreen(int scrn,int fd,const __DRIextension ** extensions,const __DRIconfig *** driver_configs,void * data)465 dril2CreateNewScreen(int scrn, int fd,
466 const __DRIextension **extensions,
467 const __DRIconfig ***driver_configs, void *data)
468 {
469 return drilCreateNewScreen(scrn, fd,
470 extensions,
471 __driDriverExtensions,
472 driver_configs, data);
473 }
474
475 static __DRIscreen *
drilSWCreateNewScreen(int scrn,const __DRIextension ** extensions,const __DRIconfig *** driver_configs,void * data)476 drilSWCreateNewScreen(int scrn, const __DRIextension **extensions,
477 const __DRIconfig ***driver_configs,
478 void *data)
479 {
480 return drilCreateNewScreen(scrn, -1,
481 extensions,
482 __driDriverExtensions,
483 driver_configs, data);
484 }
485
486 static __DRIscreen *
drilSWCreateNewScreen2(int scrn,const __DRIextension ** extensions,const __DRIextension ** driver_extensions,const __DRIconfig *** driver_configs,void * data)487 drilSWCreateNewScreen2(int scrn, const __DRIextension **extensions,
488 const __DRIextension **driver_extensions,
489 const __DRIconfig ***driver_configs, void *data)
490 {
491 return drilCreateNewScreen(scrn, -1,
492 extensions,
493 __driDriverExtensions,
494 driver_configs, data);
495 }
496
497 static int
drilSWQueryBufferAge(__DRIdrawable * pdp)498 drilSWQueryBufferAge(__DRIdrawable *pdp)
499 {
500 return 0;
501 }
502
503
504 static const __DRIswrastExtension drilSWRastExtension = {
505 .base = { __DRI_SWRAST, 5 },
506
507 .createNewScreen = drilSWCreateNewScreen,
508 .createNewDrawable = drilCreateNewDrawable,
509 .createNewContextForAPI = drilCreateNewContextForAPI,
510 .createContextAttribs = drilCreateContextAttribs,
511 .createNewScreen2 = drilSWCreateNewScreen2,
512 .queryBufferAge = drilSWQueryBufferAge,
513 };
514
515 const __DRIdri2Extension drilDRI2Extension = {
516 .base = { __DRI_DRI2, 5 },
517
518 /* these are the methods used by the xserver */
519 .createNewScreen = dril2CreateNewScreen,
520 .createNewDrawable = drilCreateNewDrawable,
521 .createNewContext = drilCreateNewContext,
522 .createContextAttribs = drilCreateContextAttribs,
523 };
524
525 const __DRIextension *__driDriverExtensions[] = {
526 &drilCoreExtension.base,
527 &drilSWRastExtension.base,
528 &drilDRI2Extension.base,
529 NULL
530 };
531
532 #include "util/detect_os.h"
533
534 #include "target-helpers/drm_helper.h"
535 #include "target-helpers/sw_helper.h"
536
537 #define DEFINE_LOADER_DRM_ENTRYPOINT(drivername) \
538 const __DRIextension **__driDriverGetExtensions_##drivername(void); \
539 PUBLIC const __DRIextension **__driDriverGetExtensions_##drivername(void) \
540 { \
541 return __driDriverExtensions; \
542 }
543
544 const __DRIextension **__driDriverGetExtensions_swrast(void);
545
__driDriverGetExtensions_swrast(void)546 PUBLIC const __DRIextension **__driDriverGetExtensions_swrast(void)
547 {
548 return __driDriverExtensions;
549 }
550
551 const __DRIextension **__driDriverGetExtensions_kms_swrast(void);
552
__driDriverGetExtensions_kms_swrast(void)553 PUBLIC const __DRIextension **__driDriverGetExtensions_kms_swrast(void)
554 {
555 return __driDriverExtensions;
556 }
557
558 DEFINE_LOADER_DRM_ENTRYPOINT(i915)
559 DEFINE_LOADER_DRM_ENTRYPOINT(iris)
560 DEFINE_LOADER_DRM_ENTRYPOINT(crocus)
561 DEFINE_LOADER_DRM_ENTRYPOINT(nouveau)
562 DEFINE_LOADER_DRM_ENTRYPOINT(r300)
563 DEFINE_LOADER_DRM_ENTRYPOINT(r600)
564 DEFINE_LOADER_DRM_ENTRYPOINT(radeonsi)
565 DEFINE_LOADER_DRM_ENTRYPOINT(vmwgfx)
566 DEFINE_LOADER_DRM_ENTRYPOINT(msm)
567 DEFINE_LOADER_DRM_ENTRYPOINT(kgsl)
568 DEFINE_LOADER_DRM_ENTRYPOINT(virtio_gpu)
569 DEFINE_LOADER_DRM_ENTRYPOINT(v3d)
570 DEFINE_LOADER_DRM_ENTRYPOINT(vc4)
571 DEFINE_LOADER_DRM_ENTRYPOINT(panfrost)
572 DEFINE_LOADER_DRM_ENTRYPOINT(panthor)
573 DEFINE_LOADER_DRM_ENTRYPOINT(asahi)
574 DEFINE_LOADER_DRM_ENTRYPOINT(etnaviv)
575 DEFINE_LOADER_DRM_ENTRYPOINT(tegra)
576 DEFINE_LOADER_DRM_ENTRYPOINT(armada_drm)
577 DEFINE_LOADER_DRM_ENTRYPOINT(exynos)
578 DEFINE_LOADER_DRM_ENTRYPOINT(gm12u320)
579 DEFINE_LOADER_DRM_ENTRYPOINT(hdlcd)
580 DEFINE_LOADER_DRM_ENTRYPOINT(hx8357d)
581 DEFINE_LOADER_DRM_ENTRYPOINT(ili9163)
582 DEFINE_LOADER_DRM_ENTRYPOINT(ili9225)
583 DEFINE_LOADER_DRM_ENTRYPOINT(ili9341)
584 DEFINE_LOADER_DRM_ENTRYPOINT(ili9486)
585 DEFINE_LOADER_DRM_ENTRYPOINT(imx_drm)
586 DEFINE_LOADER_DRM_ENTRYPOINT(imx_dcss)
587 DEFINE_LOADER_DRM_ENTRYPOINT(imx_lcdif)
588 DEFINE_LOADER_DRM_ENTRYPOINT(ingenic_drm)
589 DEFINE_LOADER_DRM_ENTRYPOINT(kirin)
590 DEFINE_LOADER_DRM_ENTRYPOINT(komeda)
591 DEFINE_LOADER_DRM_ENTRYPOINT(mali_dp)
592 DEFINE_LOADER_DRM_ENTRYPOINT(mcde)
593 DEFINE_LOADER_DRM_ENTRYPOINT(mediatek)
594 DEFINE_LOADER_DRM_ENTRYPOINT(meson)
595 DEFINE_LOADER_DRM_ENTRYPOINT(mi0283qt)
596 DEFINE_LOADER_DRM_ENTRYPOINT(mxsfb_drm)
597 DEFINE_LOADER_DRM_ENTRYPOINT(panel_mipi_dbi)
598 DEFINE_LOADER_DRM_ENTRYPOINT(pl111)
599 DEFINE_LOADER_DRM_ENTRYPOINT(rcar_du)
600 DEFINE_LOADER_DRM_ENTRYPOINT(repaper)
601 DEFINE_LOADER_DRM_ENTRYPOINT(rockchip)
602 DEFINE_LOADER_DRM_ENTRYPOINT(rzg2l_du)
603 DEFINE_LOADER_DRM_ENTRYPOINT(ssd130x)
604 DEFINE_LOADER_DRM_ENTRYPOINT(st7586)
605 DEFINE_LOADER_DRM_ENTRYPOINT(st7735r)
606 DEFINE_LOADER_DRM_ENTRYPOINT(sti)
607 DEFINE_LOADER_DRM_ENTRYPOINT(stm)
608 DEFINE_LOADER_DRM_ENTRYPOINT(sun4i_drm)
609 DEFINE_LOADER_DRM_ENTRYPOINT(udl)
610 DEFINE_LOADER_DRM_ENTRYPOINT(zynqmp_dpsub)
611 DEFINE_LOADER_DRM_ENTRYPOINT(lima)
612 DEFINE_LOADER_DRM_ENTRYPOINT(d3d12)
613 DEFINE_LOADER_DRM_ENTRYPOINT(zink)
614