Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Copyright © 2010 Intel Corporation |
||
3 | * |
||
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
5 | * copy of this software and associated documentation files (the "Software"), |
||
6 | * to deal in the Software without restriction, including without limitation |
||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
8 | * and/or sell copies of the Software, and to permit persons to whom the |
||
9 | * Software is furnished to do so, subject to the following conditions: |
||
10 | * |
||
11 | * The above copyright notice and this permission notice (including the next |
||
12 | * paragraph) shall be included in all copies or substantial portions of the |
||
13 | * Software. |
||
14 | * |
||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||
16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||
18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
||
19 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
||
20 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
22 | * DEALINGS IN THE SOFTWARE. |
||
23 | * |
||
24 | * Authors: |
||
25 | * Kristian Høgsberg |
||
26 | */ |
||
27 | |||
28 | #define WL_HIDE_DEPRECATED |
||
29 | |||
30 | #include |
||
31 | #include |
||
32 | #include |
||
33 | #include |
||
34 | #include |
||
35 | #include |
||
36 | #include |
||
37 | #include |
||
38 | #include |
||
39 | #ifdef HAVE_LIBDRM |
||
40 | #include |
||
41 | #include |
||
42 | #endif |
||
43 | #include |
||
44 | #include |
||
45 | #include |
||
46 | #include |
||
47 | |||
48 | #ifdef HAVE_WAYLAND_PLATFORM |
||
49 | #include "wayland-drm.h" |
||
50 | #include "wayland-drm-client-protocol.h" |
||
51 | #endif |
||
52 | |||
53 | #include "egl_dri2.h" |
||
54 | #include "../util/u_atomic.h" |
||
55 | |||
56 | const __DRIuseInvalidateExtension use_invalidate = { |
||
57 | .base = { __DRI_USE_INVALIDATE, 1 } |
||
58 | }; |
||
59 | |||
60 | EGLint dri2_to_egl_attribute_map[] = { |
||
61 | 0, |
||
62 | EGL_BUFFER_SIZE, /* __DRI_ATTRIB_BUFFER_SIZE */ |
||
63 | EGL_LEVEL, /* __DRI_ATTRIB_LEVEL */ |
||
64 | EGL_RED_SIZE, /* __DRI_ATTRIB_RED_SIZE */ |
||
65 | EGL_GREEN_SIZE, /* __DRI_ATTRIB_GREEN_SIZE */ |
||
66 | EGL_BLUE_SIZE, /* __DRI_ATTRIB_BLUE_SIZE */ |
||
67 | EGL_LUMINANCE_SIZE, /* __DRI_ATTRIB_LUMINANCE_SIZE */ |
||
68 | EGL_ALPHA_SIZE, /* __DRI_ATTRIB_ALPHA_SIZE */ |
||
69 | 0, /* __DRI_ATTRIB_ALPHA_MASK_SIZE */ |
||
70 | EGL_DEPTH_SIZE, /* __DRI_ATTRIB_DEPTH_SIZE */ |
||
71 | EGL_STENCIL_SIZE, /* __DRI_ATTRIB_STENCIL_SIZE */ |
||
72 | 0, /* __DRI_ATTRIB_ACCUM_RED_SIZE */ |
||
73 | 0, /* __DRI_ATTRIB_ACCUM_GREEN_SIZE */ |
||
74 | 0, /* __DRI_ATTRIB_ACCUM_BLUE_SIZE */ |
||
75 | 0, /* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */ |
||
76 | EGL_SAMPLE_BUFFERS, /* __DRI_ATTRIB_SAMPLE_BUFFERS */ |
||
77 | EGL_SAMPLES, /* __DRI_ATTRIB_SAMPLES */ |
||
78 | 0, /* __DRI_ATTRIB_RENDER_TYPE, */ |
||
79 | 0, /* __DRI_ATTRIB_CONFIG_CAVEAT */ |
||
80 | 0, /* __DRI_ATTRIB_CONFORMANT */ |
||
81 | 0, /* __DRI_ATTRIB_DOUBLE_BUFFER */ |
||
82 | 0, /* __DRI_ATTRIB_STEREO */ |
||
83 | 0, /* __DRI_ATTRIB_AUX_BUFFERS */ |
||
84 | 0, /* __DRI_ATTRIB_TRANSPARENT_TYPE */ |
||
85 | 0, /* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */ |
||
86 | 0, /* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */ |
||
87 | 0, /* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */ |
||
88 | 0, /* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */ |
||
89 | 0, /* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */ |
||
90 | 0, /* __DRI_ATTRIB_FLOAT_MODE (deprecated) */ |
||
91 | 0, /* __DRI_ATTRIB_RED_MASK */ |
||
92 | 0, /* __DRI_ATTRIB_GREEN_MASK */ |
||
93 | 0, /* __DRI_ATTRIB_BLUE_MASK */ |
||
94 | 0, /* __DRI_ATTRIB_ALPHA_MASK */ |
||
95 | EGL_MAX_PBUFFER_WIDTH, /* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */ |
||
96 | EGL_MAX_PBUFFER_HEIGHT, /* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */ |
||
97 | EGL_MAX_PBUFFER_PIXELS, /* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */ |
||
98 | 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */ |
||
99 | 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */ |
||
100 | 0, /* __DRI_ATTRIB_VISUAL_SELECT_GROUP */ |
||
101 | 0, /* __DRI_ATTRIB_SWAP_METHOD */ |
||
102 | EGL_MAX_SWAP_INTERVAL, /* __DRI_ATTRIB_MAX_SWAP_INTERVAL */ |
||
103 | EGL_MIN_SWAP_INTERVAL, /* __DRI_ATTRIB_MIN_SWAP_INTERVAL */ |
||
104 | 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */ |
||
105 | 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */ |
||
106 | 0, /* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */ |
||
107 | 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */ |
||
108 | EGL_Y_INVERTED_NOK, /* __DRI_ATTRIB_YINVERTED */ |
||
109 | 0, /* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */ |
||
110 | }; |
||
111 | |||
112 | static EGLBoolean |
||
113 | dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) |
||
114 | { |
||
115 | if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0) |
||
116 | return EGL_FALSE; |
||
117 | |||
118 | if (!_eglMatchConfig(conf, criteria)) |
||
119 | return EGL_FALSE; |
||
120 | |||
121 | return EGL_TRUE; |
||
122 | } |
||
123 | |||
124 | struct dri2_egl_config * |
||
125 | dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, |
||
126 | EGLint surface_type, const EGLint *attr_list, |
||
127 | const unsigned int *rgba_masks) |
||
128 | { |
||
129 | struct dri2_egl_config *conf; |
||
130 | struct dri2_egl_display *dri2_dpy; |
||
131 | _EGLConfig base; |
||
132 | unsigned int attrib, value, double_buffer; |
||
133 | EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; |
||
134 | unsigned int dri_masks[4] = { 0, 0, 0, 0 }; |
||
135 | _EGLConfig *matching_config; |
||
136 | EGLint num_configs = 0; |
||
137 | EGLint config_id; |
||
138 | int i; |
||
139 | |||
140 | dri2_dpy = disp->DriverData; |
||
141 | _eglInitConfig(&base, disp, id); |
||
142 | |||
143 | i = 0; |
||
144 | double_buffer = 0; |
||
145 | bind_to_texture_rgb = 0; |
||
146 | bind_to_texture_rgba = 0; |
||
147 | |||
148 | while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) { |
||
149 | switch (attrib) { |
||
150 | case __DRI_ATTRIB_RENDER_TYPE: |
||
151 | if (value & __DRI_ATTRIB_RGBA_BIT) |
||
152 | value = EGL_RGB_BUFFER; |
||
153 | else if (value & __DRI_ATTRIB_LUMINANCE_BIT) |
||
154 | value = EGL_LUMINANCE_BUFFER; |
||
155 | else |
||
156 | return NULL; |
||
157 | _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value); |
||
158 | break; |
||
159 | |||
160 | case __DRI_ATTRIB_CONFIG_CAVEAT: |
||
161 | if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) |
||
162 | value = EGL_NON_CONFORMANT_CONFIG; |
||
163 | else if (value & __DRI_ATTRIB_SLOW_BIT) |
||
164 | value = EGL_SLOW_CONFIG; |
||
165 | else |
||
166 | value = EGL_NONE; |
||
167 | _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value); |
||
168 | break; |
||
169 | |||
170 | case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: |
||
171 | bind_to_texture_rgb = value; |
||
172 | break; |
||
173 | |||
174 | case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: |
||
175 | bind_to_texture_rgba = value; |
||
176 | break; |
||
177 | |||
178 | case __DRI_ATTRIB_DOUBLE_BUFFER: |
||
179 | double_buffer = value; |
||
180 | break; |
||
181 | |||
182 | case __DRI_ATTRIB_RED_MASK: |
||
183 | dri_masks[0] = value; |
||
184 | break; |
||
185 | |||
186 | case __DRI_ATTRIB_GREEN_MASK: |
||
187 | dri_masks[1] = value; |
||
188 | break; |
||
189 | |||
190 | case __DRI_ATTRIB_BLUE_MASK: |
||
191 | dri_masks[2] = value; |
||
192 | break; |
||
193 | |||
194 | case __DRI_ATTRIB_ALPHA_MASK: |
||
195 | dri_masks[3] = value; |
||
196 | break; |
||
197 | |||
198 | case __DRI_ATTRIB_ACCUM_RED_SIZE: |
||
199 | case __DRI_ATTRIB_ACCUM_GREEN_SIZE: |
||
200 | case __DRI_ATTRIB_ACCUM_BLUE_SIZE: |
||
201 | case __DRI_ATTRIB_ACCUM_ALPHA_SIZE: |
||
202 | /* Don't expose visuals with the accumulation buffer. */ |
||
203 | if (value > 0) |
||
204 | return NULL; |
||
205 | break; |
||
206 | |||
207 | default: |
||
208 | key = dri2_to_egl_attribute_map[attrib]; |
||
209 | if (key != 0) |
||
210 | _eglSetConfigKey(&base, key, value); |
||
211 | break; |
||
212 | } |
||
213 | } |
||
214 | |||
215 | if (attr_list) |
||
216 | for (i = 0; attr_list[i] != EGL_NONE; i += 2) |
||
217 | _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]); |
||
218 | |||
219 | if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks))) |
||
220 | return NULL; |
||
221 | |||
222 | base.NativeRenderable = EGL_TRUE; |
||
223 | |||
224 | base.SurfaceType = surface_type; |
||
225 | if (surface_type & (EGL_PBUFFER_BIT | |
||
226 | (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) { |
||
227 | base.BindToTextureRGB = bind_to_texture_rgb; |
||
228 | if (base.AlphaSize > 0) |
||
229 | base.BindToTextureRGBA = bind_to_texture_rgba; |
||
230 | } |
||
231 | |||
232 | base.RenderableType = disp->ClientAPIs; |
||
233 | base.Conformant = disp->ClientAPIs; |
||
234 | |||
235 | base.MinSwapInterval = dri2_dpy->min_swap_interval; |
||
236 | base.MaxSwapInterval = dri2_dpy->max_swap_interval; |
||
237 | |||
238 | if (!_eglValidateConfig(&base, EGL_FALSE)) { |
||
239 | _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); |
||
240 | return NULL; |
||
241 | } |
||
242 | |||
243 | config_id = base.ConfigID; |
||
244 | base.ConfigID = EGL_DONT_CARE; |
||
245 | base.SurfaceType = EGL_DONT_CARE; |
||
246 | num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1, |
||
247 | (_EGLArrayForEach) dri2_match_config, &base); |
||
248 | |||
249 | if (num_configs == 1) { |
||
250 | conf = (struct dri2_egl_config *) matching_config; |
||
251 | |||
252 | if (double_buffer && !conf->dri_double_config) |
||
253 | conf->dri_double_config = dri_config; |
||
254 | else if (!double_buffer && !conf->dri_single_config) |
||
255 | conf->dri_single_config = dri_config; |
||
256 | else |
||
257 | /* a similar config type is already added (unlikely) => discard */ |
||
258 | return NULL; |
||
259 | } |
||
260 | else if (num_configs == 0) { |
||
261 | conf = malloc(sizeof *conf); |
||
262 | if (conf == NULL) |
||
263 | return NULL; |
||
264 | |||
265 | memcpy(&conf->base, &base, sizeof base); |
||
266 | if (double_buffer) { |
||
267 | conf->dri_double_config = dri_config; |
||
268 | conf->dri_single_config = NULL; |
||
269 | } else { |
||
270 | conf->dri_single_config = dri_config; |
||
271 | conf->dri_double_config = NULL; |
||
272 | } |
||
273 | conf->base.SurfaceType = 0; |
||
274 | conf->base.ConfigID = config_id; |
||
275 | |||
276 | _eglLinkConfig(&conf->base); |
||
277 | } |
||
278 | else { |
||
279 | assert(0); |
||
280 | return NULL; |
||
281 | } |
||
282 | |||
283 | if (double_buffer) { |
||
284 | surface_type &= ~EGL_PIXMAP_BIT; |
||
285 | } |
||
286 | |||
287 | conf->base.SurfaceType |= surface_type; |
||
288 | |||
289 | return conf; |
||
290 | } |
||
291 | |||
292 | __DRIimage * |
||
293 | dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) |
||
294 | { |
||
295 | _EGLDisplay *disp = data; |
||
296 | struct dri2_egl_image *dri2_img; |
||
297 | _EGLImage *img; |
||
298 | |||
299 | (void) screen; |
||
300 | |||
301 | img = _eglLookupImage(image, disp); |
||
302 | if (img == NULL) { |
||
303 | _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image"); |
||
304 | return NULL; |
||
305 | } |
||
306 | |||
307 | dri2_img = dri2_egl_image(image); |
||
308 | |||
309 | return dri2_img->dri_image; |
||
310 | } |
||
311 | |||
312 | const __DRIimageLookupExtension image_lookup_extension = { |
||
313 | .base = { __DRI_IMAGE_LOOKUP, 1 }, |
||
314 | |||
315 | .lookupEGLImage = dri2_lookup_egl_image |
||
316 | }; |
||
317 | |||
318 | struct dri2_extension_match { |
||
319 | const char *name; |
||
320 | int version; |
||
321 | int offset; |
||
322 | }; |
||
323 | |||
324 | static struct dri2_extension_match dri2_driver_extensions[] = { |
||
325 | { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, |
||
326 | { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) }, |
||
327 | { NULL, 0, 0 } |
||
328 | }; |
||
329 | |||
330 | static struct dri2_extension_match dri2_core_extensions[] = { |
||
331 | { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) }, |
||
332 | { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, |
||
333 | { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, |
||
334 | { NULL, 0, 0 } |
||
335 | }; |
||
336 | |||
337 | static struct dri2_extension_match swrast_driver_extensions[] = { |
||
338 | { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, |
||
339 | { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) }, |
||
340 | { NULL, 0, 0 } |
||
341 | }; |
||
342 | |||
343 | static struct dri2_extension_match swrast_core_extensions[] = { |
||
344 | { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, |
||
345 | { NULL, 0, 0 } |
||
346 | }; |
||
347 | |||
348 | static EGLBoolean |
||
349 | dri2_bind_extensions(struct dri2_egl_display *dri2_dpy, |
||
350 | struct dri2_extension_match *matches, |
||
351 | const __DRIextension **extensions) |
||
352 | { |
||
353 | int i, j, ret = EGL_TRUE; |
||
354 | void *field; |
||
355 | |||
356 | for (i = 0; extensions[i]; i++) { |
||
357 | _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name); |
||
358 | for (j = 0; matches[j].name; j++) { |
||
359 | if (strcmp(extensions[i]->name, matches[j].name) == 0 && |
||
360 | extensions[i]->version >= matches[j].version) { |
||
361 | field = ((char *) dri2_dpy + matches[j].offset); |
||
362 | *(const __DRIextension **) field = extensions[i]; |
||
363 | _eglLog(_EGL_INFO, "DRI2: found extension %s version %d", |
||
364 | extensions[i]->name, extensions[i]->version); |
||
365 | } |
||
366 | } |
||
367 | } |
||
368 | |||
369 | for (j = 0; matches[j].name; j++) { |
||
370 | field = ((char *) dri2_dpy + matches[j].offset); |
||
371 | if (*(const __DRIextension **) field == NULL) { |
||
372 | _eglLog(_EGL_WARNING, "DRI2: did not find extension %s version %d", |
||
373 | matches[j].name, matches[j].version); |
||
374 | ret = EGL_FALSE; |
||
375 | } |
||
376 | } |
||
377 | |||
378 | return ret; |
||
379 | } |
||
380 | |||
381 | #if 0 |
||
382 | |||
383 | static const __DRIextension ** |
||
384 | dri2_open_driver(_EGLDisplay *disp) |
||
385 | { |
||
386 | struct dri2_egl_display *dri2_dpy = disp->DriverData; |
||
387 | const __DRIextension **extensions = NULL; |
||
388 | char path[PATH_MAX], *search_paths, *p, *next, *end; |
||
389 | char *get_extensions_name; |
||
390 | const __DRIextension **(*get_extensions)(void); |
||
391 | |||
392 | search_paths = NULL; |
||
393 | if (geteuid() == getuid()) { |
||
394 | /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ |
||
395 | search_paths = getenv("LIBGL_DRIVERS_PATH"); |
||
396 | } |
||
397 | if (search_paths == NULL) |
||
398 | search_paths = DEFAULT_DRIVER_DIR; |
||
399 | |||
400 | dri2_dpy->driver = NULL; |
||
401 | end = search_paths + strlen(search_paths); |
||
402 | for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) { |
||
403 | int len; |
||
404 | next = strchr(p, ':'); |
||
405 | if (next == NULL) |
||
406 | next = end; |
||
407 | |||
408 | len = next - p; |
||
409 | #if GLX_USE_TLS |
||
410 | snprintf(path, sizeof path, |
||
411 | "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name); |
||
412 | dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); |
||
413 | #endif |
||
414 | if (dri2_dpy->driver == NULL) { |
||
415 | snprintf(path, sizeof path, |
||
416 | "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name); |
||
417 | dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); |
||
418 | if (dri2_dpy->driver == NULL) |
||
419 | _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror()); |
||
420 | } |
||
421 | /* not need continue to loop all paths once the driver is found */ |
||
422 | if (dri2_dpy->driver != NULL) |
||
423 | break; |
||
424 | } |
||
425 | |||
426 | if (dri2_dpy->driver == NULL) { |
||
427 | _eglLog(_EGL_WARNING, |
||
428 | "DRI2: failed to open %s (search paths %s)", |
||
429 | dri2_dpy->driver_name, search_paths); |
||
430 | return NULL; |
||
431 | } |
||
432 | |||
433 | _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path); |
||
434 | |||
435 | if (asprintf(&get_extensions_name, "%s_%s", |
||
436 | __DRI_DRIVER_GET_EXTENSIONS, dri2_dpy->driver_name) != -1) { |
||
437 | get_extensions = dlsym(dri2_dpy->driver, get_extensions_name); |
||
438 | if (get_extensions) { |
||
439 | extensions = get_extensions(); |
||
440 | } else { |
||
441 | _eglLog(_EGL_DEBUG, "driver does not expose %s(): %s\n", |
||
442 | get_extensions_name, dlerror()); |
||
443 | } |
||
444 | free(get_extensions_name); |
||
445 | } |
||
446 | |||
447 | if (!extensions) |
||
448 | extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS); |
||
449 | if (extensions == NULL) { |
||
450 | _eglLog(_EGL_WARNING, |
||
451 | "DRI2: driver exports no extensions (%s)", dlerror()); |
||
452 | dlclose(dri2_dpy->driver); |
||
453 | } |
||
454 | |||
455 | return extensions; |
||
456 | } |
||
457 | |||
458 | EGLBoolean |
||
459 | dri2_load_driver(_EGLDisplay *disp) |
||
460 | { |
||
461 | struct dri2_egl_display *dri2_dpy = disp->DriverData; |
||
462 | const __DRIextension **extensions; |
||
463 | |||
464 | extensions = dri2_open_driver(disp); |
||
465 | if (!extensions) |
||
466 | return EGL_FALSE; |
||
467 | |||
468 | if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) { |
||
469 | dlclose(dri2_dpy->driver); |
||
470 | return EGL_FALSE; |
||
471 | } |
||
472 | dri2_dpy->driver_extensions = extensions; |
||
473 | |||
474 | return EGL_TRUE; |
||
475 | } |
||
476 | |||
477 | EGLBoolean |
||
478 | dri2_load_driver_swrast(_EGLDisplay *disp) |
||
479 | { |
||
480 | struct dri2_egl_display *dri2_dpy = disp->DriverData; |
||
481 | const __DRIextension **extensions; |
||
482 | |||
483 | extensions = dri2_open_driver(disp); |
||
484 | if (!extensions) |
||
485 | return EGL_FALSE; |
||
486 | |||
487 | if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) { |
||
488 | dlclose(dri2_dpy->driver); |
||
489 | return EGL_FALSE; |
||
490 | } |
||
491 | dri2_dpy->driver_extensions = extensions; |
||
492 | |||
493 | return EGL_TRUE; |
||
494 | } |
||
495 | #endif |
||
496 | |||
497 | void |
||
498 | dri2_setup_screen(_EGLDisplay *disp) |
||
499 | { |
||
500 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
501 | unsigned int api_mask; |
||
502 | |||
503 | if (dri2_dpy->dri2) { |
||
504 | api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); |
||
505 | } else { |
||
506 | assert(dri2_dpy->swrast); |
||
507 | api_mask = 1 << __DRI_API_OPENGL | |
||
508 | 1 << __DRI_API_GLES | |
||
509 | 1 << __DRI_API_GLES2 | |
||
510 | 1 << __DRI_API_GLES3; |
||
511 | } |
||
512 | |||
513 | disp->ClientAPIs = 0; |
||
514 | if (api_mask & (1 <<__DRI_API_OPENGL)) |
||
515 | disp->ClientAPIs |= EGL_OPENGL_BIT; |
||
516 | if (api_mask & (1 <<__DRI_API_GLES)) |
||
517 | disp->ClientAPIs |= EGL_OPENGL_ES_BIT; |
||
518 | if (api_mask & (1 << __DRI_API_GLES2)) |
||
519 | disp->ClientAPIs |= EGL_OPENGL_ES2_BIT; |
||
520 | if (api_mask & (1 << __DRI_API_GLES3)) |
||
521 | disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR; |
||
522 | |||
523 | assert(dri2_dpy->dri2 || dri2_dpy->swrast); |
||
524 | disp->Extensions.KHR_surfaceless_context = EGL_TRUE; |
||
525 | disp->Extensions.MESA_configless_context = EGL_TRUE; |
||
526 | |||
527 | if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) { |
||
528 | disp->Extensions.KHR_create_context = EGL_TRUE; |
||
529 | |||
530 | if (dri2_dpy->robustness) |
||
531 | disp->Extensions.EXT_create_context_robustness = EGL_TRUE; |
||
532 | } |
||
533 | |||
534 | if (dri2_dpy->fence) { |
||
535 | disp->Extensions.KHR_fence_sync = EGL_TRUE; |
||
536 | disp->Extensions.KHR_wait_sync = EGL_TRUE; |
||
537 | if (dri2_dpy->fence->get_fence_from_cl_event) |
||
538 | disp->Extensions.KHR_cl_event2 = EGL_TRUE; |
||
539 | } |
||
540 | |||
541 | if (dri2_dpy->image) { |
||
542 | if (dri2_dpy->image->base.version >= 10 && |
||
543 | dri2_dpy->image->getCapabilities != NULL) { |
||
544 | int capabilities; |
||
545 | |||
546 | capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen); |
||
547 | disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0; |
||
548 | |||
549 | if (dri2_dpy->image->base.version >= 11) |
||
550 | disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE; |
||
551 | } else { |
||
552 | disp->Extensions.MESA_drm_image = EGL_TRUE; |
||
553 | if (dri2_dpy->image->base.version >= 11) |
||
554 | disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE; |
||
555 | } |
||
556 | |||
557 | disp->Extensions.KHR_image_base = EGL_TRUE; |
||
558 | disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; |
||
559 | if (dri2_dpy->image->base.version >= 5 && |
||
560 | dri2_dpy->image->createImageFromTexture) { |
||
561 | disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; |
||
562 | disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE; |
||
563 | } |
||
564 | #ifdef HAVE_LIBDRM |
||
565 | if (dri2_dpy->image->base.version >= 8 && |
||
566 | dri2_dpy->image->createImageFromDmaBufs) { |
||
567 | disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE; |
||
568 | } |
||
569 | #endif |
||
570 | } |
||
571 | } |
||
572 | |||
573 | /* All platforms but DRM call this function to create the screen, query the |
||
574 | * dri extensions, setup the vtables and populate the driver_configs. |
||
575 | * DRM inherits all that information from its display - GBM. |
||
576 | */ |
||
577 | EGLBoolean |
||
578 | dri2_create_screen(_EGLDisplay *disp) |
||
579 | { |
||
580 | const __DRIextension **extensions; |
||
581 | struct dri2_egl_display *dri2_dpy; |
||
582 | unsigned i; |
||
583 | |||
584 | dri2_dpy = disp->DriverData; |
||
585 | |||
586 | if (dri2_dpy->dri2) { |
||
587 | if (dri2_dpy->dri2->base.version >= 4) { |
||
588 | dri2_dpy->dri_screen = |
||
589 | dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd, |
||
590 | dri2_dpy->extensions, |
||
591 | dri2_dpy->driver_extensions, |
||
592 | &dri2_dpy->driver_configs, disp); |
||
593 | } else { |
||
594 | dri2_dpy->dri_screen = |
||
595 | dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, |
||
596 | dri2_dpy->extensions, |
||
597 | &dri2_dpy->driver_configs, disp); |
||
598 | } |
||
599 | } else { |
||
600 | assert(dri2_dpy->swrast); |
||
601 | if (dri2_dpy->swrast->base.version >= 4) { |
||
602 | dri2_dpy->dri_screen = |
||
603 | dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->extensions, |
||
604 | dri2_dpy->driver_extensions, |
||
605 | &dri2_dpy->driver_configs, disp); |
||
606 | } else { |
||
607 | dri2_dpy->dri_screen = |
||
608 | dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions, |
||
609 | &dri2_dpy->driver_configs, disp); |
||
610 | } |
||
611 | } |
||
612 | |||
613 | if (dri2_dpy->dri_screen == NULL) { |
||
614 | _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); |
||
615 | return EGL_FALSE; |
||
616 | } |
||
617 | |||
618 | dri2_dpy->own_dri_screen = 1; |
||
619 | |||
620 | extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); |
||
621 | |||
622 | if (dri2_dpy->dri2) { |
||
623 | if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) |
||
624 | goto cleanup_dri_screen; |
||
625 | } else { |
||
626 | assert(dri2_dpy->swrast); |
||
627 | if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions)) |
||
628 | goto cleanup_dri_screen; |
||
629 | } |
||
630 | |||
631 | for (i = 0; extensions[i]; i++) { |
||
632 | if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) { |
||
633 | dri2_dpy->robustness = (__DRIrobustnessExtension *) extensions[i]; |
||
634 | } |
||
635 | if (strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0) { |
||
636 | dri2_dpy->config = (__DRI2configQueryExtension *) extensions[i]; |
||
637 | } |
||
638 | if (strcmp(extensions[i]->name, __DRI2_FENCE) == 0) { |
||
639 | dri2_dpy->fence = (__DRI2fenceExtension *) extensions[i]; |
||
640 | } |
||
641 | } |
||
642 | |||
643 | dri2_setup_screen(disp); |
||
644 | |||
645 | return EGL_TRUE; |
||
646 | |||
647 | cleanup_dri_screen: |
||
648 | dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); |
||
649 | |||
650 | return EGL_FALSE; |
||
651 | } |
||
652 | |||
653 | /** |
||
654 | * Called via eglInitialize(), GLX_drv->API.Initialize(). |
||
655 | */ |
||
656 | static EGLBoolean |
||
657 | dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp) |
||
658 | { |
||
659 | /* not until swrast_dri is supported */ |
||
660 | if (disp->Options.UseFallback) |
||
661 | return EGL_FALSE; |
||
662 | |||
663 | return dri2_initialize_drm(drv, disp); |
||
664 | |||
665 | #if 0 |
||
666 | switch (disp->Platform) { |
||
667 | #ifdef HAVE_X11_PLATFORM |
||
668 | case _EGL_PLATFORM_X11: |
||
669 | if (disp->Options.TestOnly) |
||
670 | return EGL_TRUE; |
||
671 | return dri2_initialize_x11(drv, disp); |
||
672 | #endif |
||
673 | |||
674 | #ifdef HAVE_DRM_PLATFORM |
||
675 | case _EGL_PLATFORM_DRM: |
||
676 | if (disp->Options.TestOnly) |
||
677 | return EGL_TRUE; |
||
678 | return dri2_initialize_drm(drv, disp); |
||
679 | #endif |
||
680 | #ifdef HAVE_WAYLAND_PLATFORM |
||
681 | case _EGL_PLATFORM_WAYLAND: |
||
682 | if (disp->Options.TestOnly) |
||
683 | return EGL_TRUE; |
||
684 | return dri2_initialize_wayland(drv, disp); |
||
685 | #endif |
||
686 | #ifdef HAVE_ANDROID_PLATFORM |
||
687 | case _EGL_PLATFORM_ANDROID: |
||
688 | if (disp->Options.TestOnly) |
||
689 | return EGL_TRUE; |
||
690 | return dri2_initialize_android(drv, disp); |
||
691 | #endif |
||
692 | |||
693 | default: |
||
694 | _eglLog(_EGL_WARNING, "No EGL platform enabled."); |
||
695 | return EGL_FALSE; |
||
696 | } |
||
697 | #endif |
||
698 | } |
||
699 | |||
700 | /** |
||
701 | * Called via eglTerminate(), drv->API.Terminate(). |
||
702 | */ |
||
703 | static EGLBoolean |
||
704 | dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) |
||
705 | { |
||
706 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
707 | unsigned i; |
||
708 | |||
709 | _eglReleaseDisplayResources(drv, disp); |
||
710 | _eglCleanupDisplay(disp); |
||
711 | |||
712 | if (dri2_dpy->own_dri_screen) |
||
713 | dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); |
||
714 | if (dri2_dpy->fd) |
||
715 | close(dri2_dpy->fd); |
||
716 | if (dri2_dpy->driver) |
||
717 | dlclose(dri2_dpy->driver); |
||
718 | free(dri2_dpy->device_name); |
||
719 | free(dri2_dpy->driver_name); |
||
720 | |||
721 | switch (disp->Platform) { |
||
722 | #ifdef HAVE_X11_PLATFORM |
||
723 | case _EGL_PLATFORM_X11: |
||
724 | if (dri2_dpy->own_device) { |
||
725 | xcb_disconnect(dri2_dpy->conn); |
||
726 | } |
||
727 | break; |
||
728 | #endif |
||
729 | #ifdef HAVE_DRM_PLATFORM |
||
730 | case _EGL_PLATFORM_DRM: |
||
731 | if (dri2_dpy->own_device) { |
||
732 | gbm_device_destroy(&dri2_dpy->gbm_dri->base.base); |
||
733 | } |
||
734 | break; |
||
735 | #endif |
||
736 | #ifdef HAVE_WAYLAND_PLATFORM |
||
737 | case _EGL_PLATFORM_WAYLAND: |
||
738 | if (dri2_dpy->wl_drm) |
||
739 | wl_drm_destroy(dri2_dpy->wl_drm); |
||
740 | if (dri2_dpy->wl_shm) |
||
741 | wl_shm_destroy(dri2_dpy->wl_shm); |
||
742 | wl_registry_destroy(dri2_dpy->wl_registry); |
||
743 | wl_event_queue_destroy(dri2_dpy->wl_queue); |
||
744 | if (dri2_dpy->own_device) { |
||
745 | wl_display_disconnect(dri2_dpy->wl_dpy); |
||
746 | } |
||
747 | break; |
||
748 | #endif |
||
749 | default: |
||
750 | break; |
||
751 | } |
||
752 | |||
753 | /* The drm platform does not create the screen/driver_configs but reuses |
||
754 | * the ones from the gbm device. As such the gbm itself is responsible |
||
755 | * for the cleanup. |
||
756 | */ |
||
757 | if (disp->Platform != _EGL_PLATFORM_DRM) { |
||
758 | for (i = 0; dri2_dpy->driver_configs[i]; i++) |
||
759 | free((__DRIconfig *) dri2_dpy->driver_configs[i]); |
||
760 | free(dri2_dpy->driver_configs); |
||
761 | } |
||
762 | free(dri2_dpy); |
||
763 | disp->DriverData = NULL; |
||
764 | |||
765 | return EGL_TRUE; |
||
766 | } |
||
767 | |||
768 | /** |
||
769 | * Set the error code after a call to |
||
770 | * dri2_egl_display::dri2::createContextAttribs. |
||
771 | */ |
||
772 | static void |
||
773 | dri2_create_context_attribs_error(int dri_error) |
||
774 | { |
||
775 | EGLint egl_error; |
||
776 | |||
777 | switch (dri_error) { |
||
778 | case __DRI_CTX_ERROR_SUCCESS: |
||
779 | return; |
||
780 | |||
781 | case __DRI_CTX_ERROR_NO_MEMORY: |
||
782 | egl_error = EGL_BAD_ALLOC; |
||
783 | break; |
||
784 | |||
785 | /* From the EGL_KHR_create_context spec, section "Errors": |
||
786 | * |
||
787 | * * If |
||
788 | * with the requested API major and minor version, [...] context flags, |
||
789 | * and context reset notification behavior (for client API types where |
||
790 | * these attributes are supported), then an EGL_BAD_MATCH error is |
||
791 | * generated. |
||
792 | * |
||
793 | * * If an OpenGL ES context is requested and the values for |
||
794 | * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and |
||
795 | * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that |
||
796 | * is not defined, than an EGL_BAD_MATCH error is generated. |
||
797 | * |
||
798 | * * If an OpenGL context is requested, the requested version is |
||
799 | * greater than 3.2, and the value for attribute |
||
800 | * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any |
||
801 | * bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and |
||
802 | * EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than |
||
803 | * one of these bits set; or if the implementation does not support |
||
804 | * the requested profile, then an EGL_BAD_MATCH error is generated. |
||
805 | */ |
||
806 | case __DRI_CTX_ERROR_BAD_API: |
||
807 | case __DRI_CTX_ERROR_BAD_VERSION: |
||
808 | case __DRI_CTX_ERROR_BAD_FLAG: |
||
809 | egl_error = EGL_BAD_MATCH; |
||
810 | break; |
||
811 | |||
812 | /* From the EGL_KHR_create_context spec, section "Errors": |
||
813 | * |
||
814 | * * If an attribute name or attribute value in |
||
815 | * recognized (including unrecognized bits in bitmask attributes), |
||
816 | * then an EGL_BAD_ATTRIBUTE error is generated." |
||
817 | */ |
||
818 | case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE: |
||
819 | case __DRI_CTX_ERROR_UNKNOWN_FLAG: |
||
820 | egl_error = EGL_BAD_ATTRIBUTE; |
||
821 | break; |
||
822 | |||
823 | default: |
||
824 | assert(0); |
||
825 | egl_error = EGL_BAD_MATCH; |
||
826 | break; |
||
827 | } |
||
828 | |||
829 | _eglError(egl_error, "dri2_create_context"); |
||
830 | } |
||
831 | |||
832 | /** |
||
833 | * Called via eglCreateContext(), drv->API.CreateContext(). |
||
834 | */ |
||
835 | static _EGLContext * |
||
836 | dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, |
||
837 | _EGLContext *share_list, const EGLint *attrib_list) |
||
838 | { |
||
839 | struct dri2_egl_context *dri2_ctx; |
||
840 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
841 | struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list); |
||
842 | __DRIcontext *shared = |
||
843 | dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL; |
||
844 | struct dri2_egl_config *dri2_config = dri2_egl_config(conf); |
||
845 | const __DRIconfig *dri_config; |
||
846 | int api; |
||
847 | |||
848 | (void) drv; |
||
849 | |||
850 | dri2_ctx = malloc(sizeof *dri2_ctx); |
||
851 | if (!dri2_ctx) { |
||
852 | _eglError(EGL_BAD_ALLOC, "eglCreateContext"); |
||
853 | return NULL; |
||
854 | } |
||
855 | |||
856 | if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list)) |
||
857 | goto cleanup; |
||
858 | |||
859 | switch (dri2_ctx->base.ClientAPI) { |
||
860 | case EGL_OPENGL_ES_API: |
||
861 | switch (dri2_ctx->base.ClientMajorVersion) { |
||
862 | case 1: |
||
863 | api = __DRI_API_GLES; |
||
864 | break; |
||
865 | case 2: |
||
866 | api = __DRI_API_GLES2; |
||
867 | break; |
||
868 | case 3: |
||
869 | api = __DRI_API_GLES3; |
||
870 | break; |
||
871 | default: |
||
872 | _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); |
||
873 | free(dri2_ctx); |
||
874 | return NULL; |
||
875 | } |
||
876 | break; |
||
877 | case EGL_OPENGL_API: |
||
878 | if ((dri2_ctx->base.ClientMajorVersion >= 4 |
||
879 | || (dri2_ctx->base.ClientMajorVersion == 3 |
||
880 | && dri2_ctx->base.ClientMinorVersion >= 2)) |
||
881 | && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) |
||
882 | api = __DRI_API_OPENGL_CORE; |
||
883 | else |
||
884 | api = __DRI_API_OPENGL; |
||
885 | break; |
||
886 | default: |
||
887 | _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); |
||
888 | free(dri2_ctx); |
||
889 | return NULL; |
||
890 | } |
||
891 | |||
892 | if (conf != NULL) { |
||
893 | /* The config chosen here isn't necessarily |
||
894 | * used for surfaces later. |
||
895 | * A pixmap surface will use the single config. |
||
896 | * This opportunity depends on disabling the |
||
897 | * doubleBufferMode check in |
||
898 | * src/mesa/main/context.c:check_compatible() |
||
899 | */ |
||
900 | if (dri2_config->dri_double_config) |
||
901 | dri_config = dri2_config->dri_double_config; |
||
902 | else |
||
903 | dri_config = dri2_config->dri_single_config; |
||
904 | |||
905 | /* EGL_WINDOW_BIT is set only when there is a dri_double_config. This |
||
906 | * makes sure the back buffer will always be used. |
||
907 | */ |
||
908 | if (conf->SurfaceType & EGL_WINDOW_BIT) |
||
909 | dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER; |
||
910 | } |
||
911 | else |
||
912 | dri_config = NULL; |
||
913 | |||
914 | if (dri2_dpy->dri2) { |
||
915 | if (dri2_dpy->dri2->base.version >= 3) { |
||
916 | unsigned error; |
||
917 | unsigned num_attribs = 0; |
||
918 | uint32_t ctx_attribs[8]; |
||
919 | |||
920 | ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; |
||
921 | ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion; |
||
922 | ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION; |
||
923 | ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion; |
||
924 | |||
925 | if (dri2_ctx->base.Flags != 0) { |
||
926 | /* If the implementation doesn't support the __DRI2_ROBUSTNESS |
||
927 | * extension, don't even try to send it the robust-access flag. |
||
928 | * It may explode. Instead, generate the required EGL error here. |
||
929 | */ |
||
930 | if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0 |
||
931 | && !dri2_dpy->robustness) { |
||
932 | _eglError(EGL_BAD_MATCH, "eglCreateContext"); |
||
933 | goto cleanup; |
||
934 | } |
||
935 | |||
936 | ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS; |
||
937 | ctx_attribs[num_attribs++] = dri2_ctx->base.Flags; |
||
938 | } |
||
939 | |||
940 | if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) { |
||
941 | /* If the implementation doesn't support the __DRI2_ROBUSTNESS |
||
942 | * extension, don't even try to send it a reset strategy. It may |
||
943 | * explode. Instead, generate the required EGL error here. |
||
944 | */ |
||
945 | if (!dri2_dpy->robustness) { |
||
946 | _eglError(EGL_BAD_CONFIG, "eglCreateContext"); |
||
947 | goto cleanup; |
||
948 | } |
||
949 | |||
950 | ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY; |
||
951 | ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT; |
||
952 | } |
||
953 | |||
954 | assert(num_attribs <= ARRAY_SIZE(ctx_attribs)); |
||
955 | |||
956 | dri2_ctx->dri_context = |
||
957 | dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen, |
||
958 | api, |
||
959 | dri_config, |
||
960 | shared, |
||
961 | num_attribs / 2, |
||
962 | ctx_attribs, |
||
963 | & error, |
||
964 | dri2_ctx); |
||
965 | dri2_create_context_attribs_error(error); |
||
966 | } else { |
||
967 | dri2_ctx->dri_context = |
||
968 | dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, |
||
969 | api, |
||
970 | dri_config, |
||
971 | shared, |
||
972 | dri2_ctx); |
||
973 | } |
||
974 | } else { |
||
975 | assert(dri2_dpy->swrast); |
||
976 | dri2_ctx->dri_context = |
||
977 | dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen, |
||
978 | api, |
||
979 | dri_config, |
||
980 | shared, |
||
981 | dri2_ctx); |
||
982 | } |
||
983 | |||
984 | if (!dri2_ctx->dri_context) |
||
985 | goto cleanup; |
||
986 | |||
987 | return &dri2_ctx->base; |
||
988 | |||
989 | cleanup: |
||
990 | free(dri2_ctx); |
||
991 | return NULL; |
||
992 | } |
||
993 | |||
994 | /** |
||
995 | * Called via eglDestroyContext(), drv->API.DestroyContext(). |
||
996 | */ |
||
997 | static EGLBoolean |
||
998 | dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) |
||
999 | { |
||
1000 | struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); |
||
1001 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1002 | |||
1003 | if (_eglPutContext(ctx)) { |
||
1004 | dri2_dpy->core->destroyContext(dri2_ctx->dri_context); |
||
1005 | free(dri2_ctx); |
||
1006 | } |
||
1007 | |||
1008 | return EGL_TRUE; |
||
1009 | } |
||
1010 | |||
1011 | /** |
||
1012 | * Called via eglMakeCurrent(), drv->API.MakeCurrent(). |
||
1013 | */ |
||
1014 | static EGLBoolean |
||
1015 | dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, |
||
1016 | _EGLSurface *rsurf, _EGLContext *ctx) |
||
1017 | { |
||
1018 | struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); |
||
1019 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1020 | struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf); |
||
1021 | struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf); |
||
1022 | struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); |
||
1023 | _EGLContext *old_ctx; |
||
1024 | _EGLSurface *old_dsurf, *old_rsurf; |
||
1025 | __DRIdrawable *ddraw, *rdraw; |
||
1026 | __DRIcontext *cctx; |
||
1027 | |||
1028 | /* make new bindings */ |
||
1029 | if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) |
||
1030 | return EGL_FALSE; |
||
1031 | |||
1032 | /* flush before context switch */ |
||
1033 | if (old_ctx && dri2_drv->glFlush) |
||
1034 | dri2_drv->glFlush(); |
||
1035 | |||
1036 | ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL; |
||
1037 | rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL; |
||
1038 | cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; |
||
1039 | |||
1040 | if (old_ctx) { |
||
1041 | __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; |
||
1042 | dri2_dpy->core->unbindContext(old_cctx); |
||
1043 | } |
||
1044 | |||
1045 | if ((cctx == NULL && ddraw == NULL && rdraw == NULL) || |
||
1046 | dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { |
||
1047 | if (old_dsurf) |
||
1048 | drv->API.DestroySurface(drv, disp, old_dsurf); |
||
1049 | if (old_rsurf) |
||
1050 | drv->API.DestroySurface(drv, disp, old_rsurf); |
||
1051 | if (old_ctx) |
||
1052 | drv->API.DestroyContext(drv, disp, old_ctx); |
||
1053 | |||
1054 | return EGL_TRUE; |
||
1055 | } else { |
||
1056 | /* undo the previous _eglBindContext */ |
||
1057 | _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf); |
||
1058 | assert(&dri2_ctx->base == ctx && |
||
1059 | &dri2_dsurf->base == dsurf && |
||
1060 | &dri2_rsurf->base == rsurf); |
||
1061 | |||
1062 | _eglPutSurface(dsurf); |
||
1063 | _eglPutSurface(rsurf); |
||
1064 | _eglPutContext(ctx); |
||
1065 | |||
1066 | _eglPutSurface(old_dsurf); |
||
1067 | _eglPutSurface(old_rsurf); |
||
1068 | _eglPutContext(old_ctx); |
||
1069 | |||
1070 | return EGL_FALSE; |
||
1071 | } |
||
1072 | } |
||
1073 | |||
1074 | /* |
||
1075 | * Called from eglGetProcAddress() via drv->API.GetProcAddress(). |
||
1076 | */ |
||
1077 | static _EGLProc |
||
1078 | dri2_get_proc_address(_EGLDriver *drv, const char *procname) |
||
1079 | { |
||
1080 | struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); |
||
1081 | |||
1082 | return dri2_drv->get_proc_address(procname); |
||
1083 | } |
||
1084 | |||
1085 | static _EGLSurface* |
||
1086 | dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, |
||
1087 | _EGLConfig *conf, void *native_window, |
||
1088 | const EGLint *attrib_list) |
||
1089 | { |
||
1090 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1091 | return dri2_dpy->vtbl->create_window_surface(drv, dpy, conf, native_window, |
||
1092 | attrib_list); |
||
1093 | } |
||
1094 | |||
1095 | static _EGLSurface* |
||
1096 | dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, |
||
1097 | _EGLConfig *conf, void *native_pixmap, |
||
1098 | const EGLint *attrib_list) |
||
1099 | { |
||
1100 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1101 | return dri2_dpy->vtbl->create_pixmap_surface(drv, dpy, conf, native_pixmap, |
||
1102 | attrib_list); |
||
1103 | } |
||
1104 | |||
1105 | static _EGLSurface* |
||
1106 | dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, |
||
1107 | _EGLConfig *conf, const EGLint *attrib_list) |
||
1108 | { |
||
1109 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1110 | return dri2_dpy->vtbl->create_pbuffer_surface(drv, dpy, conf, attrib_list); |
||
1111 | } |
||
1112 | |||
1113 | static EGLBoolean |
||
1114 | dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) |
||
1115 | { |
||
1116 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1117 | return dri2_dpy->vtbl->destroy_surface(drv, dpy, surf); |
||
1118 | } |
||
1119 | |||
1120 | static EGLBoolean |
||
1121 | dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, |
||
1122 | EGLint interval) |
||
1123 | { |
||
1124 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1125 | return dri2_dpy->vtbl->swap_interval(drv, dpy, surf, interval); |
||
1126 | } |
||
1127 | |||
1128 | /** |
||
1129 | * Asks the client API to flush any rendering to the drawable so that we can |
||
1130 | * do our swapbuffers. |
||
1131 | */ |
||
1132 | void |
||
1133 | dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw) |
||
1134 | { |
||
1135 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1136 | struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); |
||
1137 | |||
1138 | if (dri2_dpy->flush) { |
||
1139 | if (dri2_dpy->flush->base.version >= 4) { |
||
1140 | /* We know there's a current context because: |
||
1141 | * |
||
1142 | * "If surface is not bound to the calling thread’s current |
||
1143 | * context, an EGL_BAD_SURFACE error is generated." |
||
1144 | */ |
||
1145 | _EGLContext *ctx = _eglGetCurrentContext(); |
||
1146 | struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); |
||
1147 | |||
1148 | /* From the EGL 1.4 spec (page 52): |
||
1149 | * |
||
1150 | * "The contents of ancillary buffers are always undefined |
||
1151 | * after calling eglSwapBuffers." |
||
1152 | */ |
||
1153 | dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context, |
||
1154 | dri2_surf->dri_drawable, |
||
1155 | __DRI2_FLUSH_DRAWABLE | |
||
1156 | __DRI2_FLUSH_INVALIDATE_ANCILLARY, |
||
1157 | __DRI2_THROTTLE_SWAPBUFFER); |
||
1158 | } else { |
||
1159 | dri2_dpy->flush->flush(dri2_surf->dri_drawable); |
||
1160 | } |
||
1161 | } |
||
1162 | } |
||
1163 | |||
1164 | static EGLBoolean |
||
1165 | dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) |
||
1166 | { |
||
1167 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1168 | return dri2_dpy->vtbl->swap_buffers(drv, dpy, surf); |
||
1169 | } |
||
1170 | |||
1171 | static EGLBoolean |
||
1172 | dri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *dpy, |
||
1173 | _EGLSurface *surf, |
||
1174 | const EGLint *rects, EGLint n_rects) |
||
1175 | { |
||
1176 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1177 | return dri2_dpy->vtbl->swap_buffers_with_damage(drv, dpy, surf, |
||
1178 | rects, n_rects); |
||
1179 | } |
||
1180 | |||
1181 | static EGLBoolean |
||
1182 | dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, |
||
1183 | EGLint numRects, const EGLint *rects) |
||
1184 | { |
||
1185 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1186 | return dri2_dpy->vtbl->swap_buffers_region(drv, dpy, surf, numRects, rects); |
||
1187 | } |
||
1188 | |||
1189 | static EGLBoolean |
||
1190 | dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, |
||
1191 | EGLint x, EGLint y, EGLint width, EGLint height) |
||
1192 | { |
||
1193 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1194 | return dri2_dpy->vtbl->post_sub_buffer(drv, dpy, surf, x, y, width, height); |
||
1195 | } |
||
1196 | |||
1197 | static EGLBoolean |
||
1198 | dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, |
||
1199 | void *native_pixmap_target) |
||
1200 | { |
||
1201 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1202 | return dri2_dpy->vtbl->copy_buffers(drv, dpy, surf, native_pixmap_target); |
||
1203 | } |
||
1204 | |||
1205 | static EGLint |
||
1206 | dri2_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) |
||
1207 | { |
||
1208 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1209 | return dri2_dpy->vtbl->query_buffer_age(drv, dpy, surf); |
||
1210 | } |
||
1211 | |||
1212 | static EGLBoolean |
||
1213 | dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) |
||
1214 | { |
||
1215 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1216 | struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface); |
||
1217 | |||
1218 | (void) drv; |
||
1219 | |||
1220 | /* FIXME: If EGL allows frontbuffer rendering for window surfaces, |
||
1221 | * we need to copy fake to real here.*/ |
||
1222 | |||
1223 | if (dri2_dpy->flush != NULL) |
||
1224 | dri2_dpy->flush->flush(dri2_surf->dri_drawable); |
||
1225 | |||
1226 | return EGL_TRUE; |
||
1227 | } |
||
1228 | |||
1229 | static EGLBoolean |
||
1230 | dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine) |
||
1231 | { |
||
1232 | (void) drv; |
||
1233 | (void) disp; |
||
1234 | |||
1235 | if (engine != EGL_CORE_NATIVE_ENGINE) |
||
1236 | return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); |
||
1237 | /* glXWaitX(); */ |
||
1238 | |||
1239 | return EGL_TRUE; |
||
1240 | } |
||
1241 | |||
1242 | static EGLBoolean |
||
1243 | dri2_bind_tex_image(_EGLDriver *drv, |
||
1244 | _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) |
||
1245 | { |
||
1246 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1247 | struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); |
||
1248 | struct dri2_egl_context *dri2_ctx; |
||
1249 | _EGLContext *ctx; |
||
1250 | GLint format, target; |
||
1251 | |||
1252 | ctx = _eglGetCurrentContext(); |
||
1253 | dri2_ctx = dri2_egl_context(ctx); |
||
1254 | |||
1255 | if (!_eglBindTexImage(drv, disp, surf, buffer)) |
||
1256 | return EGL_FALSE; |
||
1257 | |||
1258 | switch (dri2_surf->base.TextureFormat) { |
||
1259 | case EGL_TEXTURE_RGB: |
||
1260 | format = __DRI_TEXTURE_FORMAT_RGB; |
||
1261 | break; |
||
1262 | case EGL_TEXTURE_RGBA: |
||
1263 | format = __DRI_TEXTURE_FORMAT_RGBA; |
||
1264 | break; |
||
1265 | default: |
||
1266 | assert(0); |
||
1267 | } |
||
1268 | |||
1269 | switch (dri2_surf->base.TextureTarget) { |
||
1270 | case EGL_TEXTURE_2D: |
||
1271 | target = GL_TEXTURE_2D; |
||
1272 | break; |
||
1273 | default: |
||
1274 | assert(0); |
||
1275 | } |
||
1276 | |||
1277 | (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context, |
||
1278 | target, format, |
||
1279 | dri2_surf->dri_drawable); |
||
1280 | |||
1281 | return EGL_TRUE; |
||
1282 | } |
||
1283 | |||
1284 | static EGLBoolean |
||
1285 | dri2_release_tex_image(_EGLDriver *drv, |
||
1286 | _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) |
||
1287 | { |
||
1288 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1289 | struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); |
||
1290 | struct dri2_egl_context *dri2_ctx; |
||
1291 | _EGLContext *ctx; |
||
1292 | GLint target; |
||
1293 | |||
1294 | ctx = _eglGetCurrentContext(); |
||
1295 | dri2_ctx = dri2_egl_context(ctx); |
||
1296 | |||
1297 | if (!_eglReleaseTexImage(drv, disp, surf, buffer)) |
||
1298 | return EGL_FALSE; |
||
1299 | |||
1300 | switch (dri2_surf->base.TextureTarget) { |
||
1301 | case EGL_TEXTURE_2D: |
||
1302 | target = GL_TEXTURE_2D; |
||
1303 | break; |
||
1304 | default: |
||
1305 | assert(0); |
||
1306 | } |
||
1307 | |||
1308 | if (dri2_dpy->tex_buffer->base.version >= 3 && |
||
1309 | dri2_dpy->tex_buffer->releaseTexBuffer != NULL) { |
||
1310 | (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context, |
||
1311 | target, |
||
1312 | dri2_surf->dri_drawable); |
||
1313 | } |
||
1314 | |||
1315 | return EGL_TRUE; |
||
1316 | } |
||
1317 | |||
1318 | static _EGLImage* |
||
1319 | dri2_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, |
||
1320 | EGLenum target, EGLClientBuffer buffer, |
||
1321 | const EGLint *attr_list) |
||
1322 | { |
||
1323 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1324 | return dri2_dpy->vtbl->create_image(drv, dpy, ctx, target, buffer, |
||
1325 | attr_list); |
||
1326 | } |
||
1327 | |||
1328 | static _EGLImage * |
||
1329 | dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image) |
||
1330 | { |
||
1331 | struct dri2_egl_image *dri2_img; |
||
1332 | |||
1333 | if (dri_image == NULL) { |
||
1334 | _eglError(EGL_BAD_ALLOC, "dri2_create_image"); |
||
1335 | return NULL; |
||
1336 | } |
||
1337 | |||
1338 | dri2_img = malloc(sizeof *dri2_img); |
||
1339 | if (!dri2_img) { |
||
1340 | _eglError(EGL_BAD_ALLOC, "dri2_create_image"); |
||
1341 | return NULL; |
||
1342 | } |
||
1343 | |||
1344 | if (!_eglInitImage(&dri2_img->base, disp)) { |
||
1345 | free(dri2_img); |
||
1346 | return NULL; |
||
1347 | } |
||
1348 | |||
1349 | dri2_img->dri_image = dri_image; |
||
1350 | |||
1351 | return &dri2_img->base; |
||
1352 | } |
||
1353 | |||
1354 | static _EGLImage * |
||
1355 | dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, |
||
1356 | EGLClientBuffer buffer, |
||
1357 | const EGLint *attr_list) |
||
1358 | { |
||
1359 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1360 | struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); |
||
1361 | GLuint renderbuffer = (GLuint) (uintptr_t) buffer; |
||
1362 | __DRIimage *dri_image; |
||
1363 | |||
1364 | if (renderbuffer == 0) { |
||
1365 | _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); |
||
1366 | return EGL_NO_IMAGE_KHR; |
||
1367 | } |
||
1368 | |||
1369 | dri_image = |
||
1370 | dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context, |
||
1371 | renderbuffer, NULL); |
||
1372 | |||
1373 | return dri2_create_image_from_dri(disp, dri_image); |
||
1374 | } |
||
1375 | |||
1376 | #ifdef HAVE_LIBDRM |
||
1377 | static _EGLImage * |
||
1378 | dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, |
||
1379 | EGLClientBuffer buffer, const EGLint *attr_list) |
||
1380 | { |
||
1381 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1382 | EGLint format, name, pitch, err; |
||
1383 | _EGLImageAttribs attrs; |
||
1384 | __DRIimage *dri_image; |
||
1385 | |||
1386 | name = (EGLint) (uintptr_t) buffer; |
||
1387 | |||
1388 | err = _eglParseImageAttribList(&attrs, disp, attr_list); |
||
1389 | if (err != EGL_SUCCESS) |
||
1390 | return NULL; |
||
1391 | |||
1392 | if (attrs.Width <= 0 || attrs.Height <= 0 || |
||
1393 | attrs.DRMBufferStrideMESA <= 0) { |
||
1394 | _eglError(EGL_BAD_PARAMETER, |
||
1395 | "bad width, height or stride"); |
||
1396 | return NULL; |
||
1397 | } |
||
1398 | |||
1399 | switch (attrs.DRMBufferFormatMESA) { |
||
1400 | case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: |
||
1401 | format = __DRI_IMAGE_FORMAT_ARGB8888; |
||
1402 | pitch = attrs.DRMBufferStrideMESA; |
||
1403 | break; |
||
1404 | default: |
||
1405 | _eglError(EGL_BAD_PARAMETER, |
||
1406 | "dri2_create_image_khr: unsupported pixmap depth"); |
||
1407 | return NULL; |
||
1408 | } |
||
1409 | |||
1410 | dri_image = |
||
1411 | dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, |
||
1412 | attrs.Width, |
||
1413 | attrs.Height, |
||
1414 | format, |
||
1415 | name, |
||
1416 | pitch, |
||
1417 | NULL); |
||
1418 | |||
1419 | return dri2_create_image_from_dri(disp, dri_image); |
||
1420 | } |
||
1421 | #endif |
||
1422 | |||
1423 | #ifdef HAVE_WAYLAND_PLATFORM |
||
1424 | |||
1425 | /* This structure describes how a wl_buffer maps to one or more |
||
1426 | * __DRIimages. A wl_drm_buffer stores the wl_drm format code and the |
||
1427 | * offsets and strides of the planes in the buffer. This table maps a |
||
1428 | * wl_drm format code to a description of the planes in the buffer |
||
1429 | * that lets us create a __DRIimage for each of the planes. */ |
||
1430 | |||
1431 | static const struct wl_drm_components_descriptor { |
||
1432 | uint32_t dri_components; |
||
1433 | EGLint components; |
||
1434 | int nplanes; |
||
1435 | } wl_drm_components[] = { |
||
1436 | { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 }, |
||
1437 | { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 }, |
||
1438 | { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 }, |
||
1439 | { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 }, |
||
1440 | { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 }, |
||
1441 | }; |
||
1442 | |||
1443 | static _EGLImage * |
||
1444 | dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, |
||
1445 | EGLClientBuffer _buffer, |
||
1446 | const EGLint *attr_list) |
||
1447 | { |
||
1448 | struct wl_drm_buffer *buffer; |
||
1449 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1450 | const struct wl_drm_components_descriptor *f; |
||
1451 | __DRIimage *dri_image; |
||
1452 | _EGLImageAttribs attrs; |
||
1453 | EGLint err; |
||
1454 | int32_t plane; |
||
1455 | |||
1456 | buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, |
||
1457 | (struct wl_resource *) _buffer); |
||
1458 | if (!buffer) |
||
1459 | return NULL; |
||
1460 | |||
1461 | err = _eglParseImageAttribList(&attrs, disp, attr_list); |
||
1462 | plane = attrs.PlaneWL; |
||
1463 | if (err != EGL_SUCCESS) { |
||
1464 | _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); |
||
1465 | return NULL; |
||
1466 | } |
||
1467 | |||
1468 | f = buffer->driver_format; |
||
1469 | if (plane < 0 || plane >= f->nplanes) { |
||
1470 | _eglError(EGL_BAD_PARAMETER, |
||
1471 | "dri2_create_image_wayland_wl_buffer (plane out of bounds)"); |
||
1472 | return NULL; |
||
1473 | } |
||
1474 | |||
1475 | dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL); |
||
1476 | |||
1477 | if (dri_image == NULL) { |
||
1478 | _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); |
||
1479 | return NULL; |
||
1480 | } |
||
1481 | |||
1482 | return dri2_create_image_from_dri(disp, dri_image); |
||
1483 | } |
||
1484 | #endif |
||
1485 | |||
1486 | static EGLBoolean |
||
1487 | dri2_get_sync_values_chromium(_EGLDisplay *dpy, _EGLSurface *surf, |
||
1488 | EGLuint64KHR *ust, EGLuint64KHR *msc, |
||
1489 | EGLuint64KHR *sbc) |
||
1490 | { |
||
1491 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1492 | return dri2_dpy->vtbl->get_sync_values(dpy, surf, ust, msc, sbc); |
||
1493 | } |
||
1494 | |||
1495 | /** |
||
1496 | * Set the error code after a call to |
||
1497 | * dri2_egl_image::dri_image::createImageFromTexture. |
||
1498 | */ |
||
1499 | static void |
||
1500 | dri2_create_image_khr_texture_error(int dri_error) |
||
1501 | { |
||
1502 | EGLint egl_error; |
||
1503 | |||
1504 | switch (dri_error) { |
||
1505 | case __DRI_IMAGE_ERROR_SUCCESS: |
||
1506 | return; |
||
1507 | |||
1508 | case __DRI_IMAGE_ERROR_BAD_ALLOC: |
||
1509 | egl_error = EGL_BAD_ALLOC; |
||
1510 | break; |
||
1511 | |||
1512 | case __DRI_IMAGE_ERROR_BAD_MATCH: |
||
1513 | egl_error = EGL_BAD_MATCH; |
||
1514 | break; |
||
1515 | |||
1516 | case __DRI_IMAGE_ERROR_BAD_PARAMETER: |
||
1517 | egl_error = EGL_BAD_PARAMETER; |
||
1518 | break; |
||
1519 | |||
1520 | default: |
||
1521 | assert(0); |
||
1522 | egl_error = EGL_BAD_MATCH; |
||
1523 | break; |
||
1524 | } |
||
1525 | |||
1526 | _eglError(egl_error, "dri2_create_image_khr_texture"); |
||
1527 | } |
||
1528 | |||
1529 | static _EGLImage * |
||
1530 | dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx, |
||
1531 | EGLenum target, |
||
1532 | EGLClientBuffer buffer, |
||
1533 | const EGLint *attr_list) |
||
1534 | { |
||
1535 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1536 | struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); |
||
1537 | struct dri2_egl_image *dri2_img; |
||
1538 | GLuint texture = (GLuint) (uintptr_t) buffer; |
||
1539 | _EGLImageAttribs attrs; |
||
1540 | GLuint depth; |
||
1541 | GLenum gl_target; |
||
1542 | unsigned error; |
||
1543 | |||
1544 | if (texture == 0) { |
||
1545 | _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); |
||
1546 | return EGL_NO_IMAGE_KHR; |
||
1547 | } |
||
1548 | |||
1549 | if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS) |
||
1550 | return EGL_NO_IMAGE_KHR; |
||
1551 | |||
1552 | switch (target) { |
||
1553 | case EGL_GL_TEXTURE_2D_KHR: |
||
1554 | depth = 0; |
||
1555 | gl_target = GL_TEXTURE_2D; |
||
1556 | break; |
||
1557 | case EGL_GL_TEXTURE_3D_KHR: |
||
1558 | depth = attrs.GLTextureZOffset; |
||
1559 | gl_target = GL_TEXTURE_3D; |
||
1560 | break; |
||
1561 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: |
||
1562 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: |
||
1563 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: |
||
1564 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: |
||
1565 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: |
||
1566 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: |
||
1567 | depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR; |
||
1568 | gl_target = GL_TEXTURE_CUBE_MAP; |
||
1569 | break; |
||
1570 | default: |
||
1571 | _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); |
||
1572 | return EGL_NO_IMAGE_KHR; |
||
1573 | } |
||
1574 | |||
1575 | dri2_img = malloc(sizeof *dri2_img); |
||
1576 | if (!dri2_img) { |
||
1577 | _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); |
||
1578 | return EGL_NO_IMAGE_KHR; |
||
1579 | } |
||
1580 | |||
1581 | if (!_eglInitImage(&dri2_img->base, disp)) { |
||
1582 | _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); |
||
1583 | free(dri2_img); |
||
1584 | return EGL_NO_IMAGE_KHR; |
||
1585 | } |
||
1586 | |||
1587 | dri2_img->dri_image = |
||
1588 | dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context, |
||
1589 | gl_target, |
||
1590 | texture, |
||
1591 | depth, |
||
1592 | attrs.GLTextureLevel, |
||
1593 | &error, |
||
1594 | dri2_img); |
||
1595 | dri2_create_image_khr_texture_error(error); |
||
1596 | |||
1597 | if (!dri2_img->dri_image) { |
||
1598 | free(dri2_img); |
||
1599 | return EGL_NO_IMAGE_KHR; |
||
1600 | } |
||
1601 | return &dri2_img->base; |
||
1602 | } |
||
1603 | |||
1604 | static struct wl_buffer* |
||
1605 | dri2_create_wayland_buffer_from_image(_EGLDriver *drv, _EGLDisplay *dpy, |
||
1606 | _EGLImage *img) |
||
1607 | { |
||
1608 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
1609 | return dri2_dpy->vtbl->create_wayland_buffer_from_image(drv, dpy, img); |
||
1610 | } |
||
1611 | |||
1612 | #ifdef HAVE_LIBDRM |
||
1613 | static EGLBoolean |
||
1614 | dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs) |
||
1615 | { |
||
1616 | unsigned i; |
||
1617 | |||
1618 | /** |
||
1619 | * The spec says: |
||
1620 | * |
||
1621 | * "Required attributes and their values are as follows: |
||
1622 | * |
||
1623 | * * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels |
||
1624 | * |
||
1625 | * * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified |
||
1626 | * by drm_fourcc.h and used as the pixel_format parameter of the |
||
1627 | * drm_mode_fb_cmd2 ioctl." |
||
1628 | * |
||
1629 | * and |
||
1630 | * |
||
1631 | * "* If |
||
1632 | * incomplete, EGL_BAD_PARAMETER is generated." |
||
1633 | */ |
||
1634 | if (attrs->Width <= 0 || attrs->Height <= 0 || |
||
1635 | !attrs->DMABufFourCC.IsPresent) { |
||
1636 | _eglError(EGL_BAD_PARAMETER, "attribute(s) missing"); |
||
1637 | return EGL_FALSE; |
||
1638 | } |
||
1639 | |||
1640 | /** |
||
1641 | * Also: |
||
1642 | * |
||
1643 | * "If |
||
1644 | * specified for a plane's pitch or offset isn't supported by EGL, |
||
1645 | * EGL_BAD_ACCESS is generated." |
||
1646 | */ |
||
1647 | for (i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) { |
||
1648 | if (attrs->DMABufPlanePitches[i].IsPresent && |
||
1649 | attrs->DMABufPlanePitches[i].Value <= 0) { |
||
1650 | _eglError(EGL_BAD_ACCESS, "invalid pitch"); |
||
1651 | return EGL_FALSE; |
||
1652 | } |
||
1653 | } |
||
1654 | |||
1655 | return EGL_TRUE; |
||
1656 | } |
||
1657 | |||
1658 | /* Returns the total number of file descriptors. Zero indicates an error. */ |
||
1659 | static unsigned |
||
1660 | dri2_check_dma_buf_format(const _EGLImageAttribs *attrs) |
||
1661 | { |
||
1662 | unsigned i, plane_n; |
||
1663 | |||
1664 | switch (attrs->DMABufFourCC.Value) { |
||
1665 | case DRM_FORMAT_RGB332: |
||
1666 | case DRM_FORMAT_BGR233: |
||
1667 | case DRM_FORMAT_XRGB4444: |
||
1668 | case DRM_FORMAT_XBGR4444: |
||
1669 | case DRM_FORMAT_RGBX4444: |
||
1670 | case DRM_FORMAT_BGRX4444: |
||
1671 | case DRM_FORMAT_ARGB4444: |
||
1672 | case DRM_FORMAT_ABGR4444: |
||
1673 | case DRM_FORMAT_RGBA4444: |
||
1674 | case DRM_FORMAT_BGRA4444: |
||
1675 | case DRM_FORMAT_XRGB1555: |
||
1676 | case DRM_FORMAT_XBGR1555: |
||
1677 | case DRM_FORMAT_RGBX5551: |
||
1678 | case DRM_FORMAT_BGRX5551: |
||
1679 | case DRM_FORMAT_ARGB1555: |
||
1680 | case DRM_FORMAT_ABGR1555: |
||
1681 | case DRM_FORMAT_RGBA5551: |
||
1682 | case DRM_FORMAT_BGRA5551: |
||
1683 | case DRM_FORMAT_RGB565: |
||
1684 | case DRM_FORMAT_BGR565: |
||
1685 | case DRM_FORMAT_RGB888: |
||
1686 | case DRM_FORMAT_BGR888: |
||
1687 | case DRM_FORMAT_XRGB8888: |
||
1688 | case DRM_FORMAT_XBGR8888: |
||
1689 | case DRM_FORMAT_RGBX8888: |
||
1690 | case DRM_FORMAT_BGRX8888: |
||
1691 | case DRM_FORMAT_ARGB8888: |
||
1692 | case DRM_FORMAT_ABGR8888: |
||
1693 | case DRM_FORMAT_RGBA8888: |
||
1694 | case DRM_FORMAT_BGRA8888: |
||
1695 | case DRM_FORMAT_XRGB2101010: |
||
1696 | case DRM_FORMAT_XBGR2101010: |
||
1697 | case DRM_FORMAT_RGBX1010102: |
||
1698 | case DRM_FORMAT_BGRX1010102: |
||
1699 | case DRM_FORMAT_ARGB2101010: |
||
1700 | case DRM_FORMAT_ABGR2101010: |
||
1701 | case DRM_FORMAT_RGBA1010102: |
||
1702 | case DRM_FORMAT_BGRA1010102: |
||
1703 | case DRM_FORMAT_YUYV: |
||
1704 | case DRM_FORMAT_YVYU: |
||
1705 | case DRM_FORMAT_UYVY: |
||
1706 | case DRM_FORMAT_VYUY: |
||
1707 | plane_n = 1; |
||
1708 | break; |
||
1709 | case DRM_FORMAT_NV12: |
||
1710 | case DRM_FORMAT_NV21: |
||
1711 | case DRM_FORMAT_NV16: |
||
1712 | case DRM_FORMAT_NV61: |
||
1713 | plane_n = 2; |
||
1714 | break; |
||
1715 | case DRM_FORMAT_YUV410: |
||
1716 | case DRM_FORMAT_YVU410: |
||
1717 | case DRM_FORMAT_YUV411: |
||
1718 | case DRM_FORMAT_YVU411: |
||
1719 | case DRM_FORMAT_YUV420: |
||
1720 | case DRM_FORMAT_YVU420: |
||
1721 | case DRM_FORMAT_YUV422: |
||
1722 | case DRM_FORMAT_YVU422: |
||
1723 | case DRM_FORMAT_YUV444: |
||
1724 | case DRM_FORMAT_YVU444: |
||
1725 | plane_n = 3; |
||
1726 | break; |
||
1727 | default: |
||
1728 | _eglError(EGL_BAD_ATTRIBUTE, "invalid format"); |
||
1729 | return 0; |
||
1730 | } |
||
1731 | |||
1732 | /** |
||
1733 | * The spec says: |
||
1734 | * |
||
1735 | * "* If |
||
1736 | * incomplete, EGL_BAD_PARAMETER is generated." |
||
1737 | */ |
||
1738 | for (i = 0; i < plane_n; ++i) { |
||
1739 | if (!attrs->DMABufPlaneFds[i].IsPresent || |
||
1740 | !attrs->DMABufPlaneOffsets[i].IsPresent || |
||
1741 | !attrs->DMABufPlanePitches[i].IsPresent) { |
||
1742 | _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing"); |
||
1743 | return 0; |
||
1744 | } |
||
1745 | } |
||
1746 | |||
1747 | /** |
||
1748 | * The spec also says: |
||
1749 | * |
||
1750 | * "If |
||
1751 | * attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is |
||
1752 | * generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_* |
||
1753 | * attributes are specified." |
||
1754 | */ |
||
1755 | for (i = plane_n; i < 3; ++i) { |
||
1756 | if (attrs->DMABufPlaneFds[i].IsPresent || |
||
1757 | attrs->DMABufPlaneOffsets[i].IsPresent || |
||
1758 | attrs->DMABufPlanePitches[i].IsPresent) { |
||
1759 | _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes"); |
||
1760 | return 0; |
||
1761 | } |
||
1762 | } |
||
1763 | |||
1764 | return plane_n; |
||
1765 | } |
||
1766 | |||
1767 | /** |
||
1768 | * The spec says: |
||
1769 | * |
||
1770 | * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the |
||
1771 | * EGL will take a reference to the dma_buf(s) which it will release at any |
||
1772 | * time while the EGLDisplay is initialized. It is the responsibility of the |
||
1773 | * application to close the dma_buf file descriptors." |
||
1774 | * |
||
1775 | * Therefore we must never close or otherwise modify the file descriptors. |
||
1776 | */ |
||
1777 | static _EGLImage * |
||
1778 | dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx, |
||
1779 | EGLClientBuffer buffer, const EGLint *attr_list) |
||
1780 | { |
||
1781 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1782 | _EGLImage *res; |
||
1783 | EGLint err; |
||
1784 | _EGLImageAttribs attrs; |
||
1785 | __DRIimage *dri_image; |
||
1786 | unsigned num_fds; |
||
1787 | unsigned i; |
||
1788 | int fds[3]; |
||
1789 | int pitches[3]; |
||
1790 | int offsets[3]; |
||
1791 | unsigned error; |
||
1792 | |||
1793 | /** |
||
1794 | * The spec says: |
||
1795 | * |
||
1796 | * ""* If |
||
1797 | * error EGL_BAD_PARAMETER is generated." |
||
1798 | */ |
||
1799 | if (buffer != NULL) { |
||
1800 | _eglError(EGL_BAD_PARAMETER, "buffer not NULL"); |
||
1801 | return NULL; |
||
1802 | } |
||
1803 | |||
1804 | err = _eglParseImageAttribList(&attrs, disp, attr_list); |
||
1805 | if (err != EGL_SUCCESS) { |
||
1806 | _eglError(err, "bad attribute"); |
||
1807 | return NULL; |
||
1808 | } |
||
1809 | |||
1810 | if (!dri2_check_dma_buf_attribs(&attrs)) |
||
1811 | return NULL; |
||
1812 | |||
1813 | num_fds = dri2_check_dma_buf_format(&attrs); |
||
1814 | if (!num_fds) |
||
1815 | return NULL; |
||
1816 | |||
1817 | for (i = 0; i < num_fds; ++i) { |
||
1818 | fds[i] = attrs.DMABufPlaneFds[i].Value; |
||
1819 | pitches[i] = attrs.DMABufPlanePitches[i].Value; |
||
1820 | offsets[i] = attrs.DMABufPlaneOffsets[i].Value; |
||
1821 | } |
||
1822 | |||
1823 | dri_image = |
||
1824 | dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, |
||
1825 | attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, |
||
1826 | fds, num_fds, pitches, offsets, |
||
1827 | attrs.DMABufYuvColorSpaceHint.Value, |
||
1828 | attrs.DMABufSampleRangeHint.Value, |
||
1829 | attrs.DMABufChromaHorizontalSiting.Value, |
||
1830 | attrs.DMABufChromaVerticalSiting.Value, |
||
1831 | &error, |
||
1832 | NULL); |
||
1833 | dri2_create_image_khr_texture_error(error); |
||
1834 | |||
1835 | if (!dri_image) |
||
1836 | return EGL_NO_IMAGE_KHR; |
||
1837 | |||
1838 | res = dri2_create_image_from_dri(disp, dri_image); |
||
1839 | |||
1840 | return res; |
||
1841 | } |
||
1842 | #endif |
||
1843 | |||
1844 | _EGLImage * |
||
1845 | dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, |
||
1846 | _EGLContext *ctx, EGLenum target, |
||
1847 | EGLClientBuffer buffer, const EGLint *attr_list) |
||
1848 | { |
||
1849 | (void) drv; |
||
1850 | |||
1851 | switch (target) { |
||
1852 | case EGL_GL_TEXTURE_2D_KHR: |
||
1853 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: |
||
1854 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: |
||
1855 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: |
||
1856 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: |
||
1857 | case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: |
||
1858 | case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: |
||
1859 | return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list); |
||
1860 | case EGL_GL_RENDERBUFFER_KHR: |
||
1861 | return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); |
||
1862 | #ifdef HAVE_LIBDRM |
||
1863 | case EGL_DRM_BUFFER_MESA: |
||
1864 | return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list); |
||
1865 | #endif |
||
1866 | #ifdef HAVE_WAYLAND_PLATFORM |
||
1867 | case EGL_WAYLAND_BUFFER_WL: |
||
1868 | return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list); |
||
1869 | #endif |
||
1870 | #ifdef HAVE_LIBDRM |
||
1871 | case EGL_LINUX_DMA_BUF_EXT: |
||
1872 | return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list); |
||
1873 | #endif |
||
1874 | default: |
||
1875 | _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); |
||
1876 | return EGL_NO_IMAGE_KHR; |
||
1877 | } |
||
1878 | } |
||
1879 | |||
1880 | static EGLBoolean |
||
1881 | dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image) |
||
1882 | { |
||
1883 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1884 | struct dri2_egl_image *dri2_img = dri2_egl_image(image); |
||
1885 | |||
1886 | (void) drv; |
||
1887 | |||
1888 | dri2_dpy->image->destroyImage(dri2_img->dri_image); |
||
1889 | free(dri2_img); |
||
1890 | |||
1891 | return EGL_TRUE; |
||
1892 | } |
||
1893 | |||
1894 | #ifdef HAVE_LIBDRM |
||
1895 | static _EGLImage * |
||
1896 | dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, |
||
1897 | const EGLint *attr_list) |
||
1898 | { |
||
1899 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1900 | struct dri2_egl_image *dri2_img; |
||
1901 | _EGLImageAttribs attrs; |
||
1902 | unsigned int dri_use, valid_mask; |
||
1903 | int format; |
||
1904 | EGLint err = EGL_SUCCESS; |
||
1905 | |||
1906 | (void) drv; |
||
1907 | |||
1908 | dri2_img = malloc(sizeof *dri2_img); |
||
1909 | if (!dri2_img) { |
||
1910 | _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); |
||
1911 | return EGL_NO_IMAGE_KHR; |
||
1912 | } |
||
1913 | |||
1914 | if (!attr_list) { |
||
1915 | err = EGL_BAD_PARAMETER; |
||
1916 | goto cleanup_img; |
||
1917 | } |
||
1918 | |||
1919 | if (!_eglInitImage(&dri2_img->base, disp)) { |
||
1920 | err = EGL_BAD_PARAMETER; |
||
1921 | goto cleanup_img; |
||
1922 | } |
||
1923 | |||
1924 | err = _eglParseImageAttribList(&attrs, disp, attr_list); |
||
1925 | if (err != EGL_SUCCESS) |
||
1926 | goto cleanup_img; |
||
1927 | |||
1928 | if (attrs.Width <= 0 || attrs.Height <= 0) { |
||
1929 | _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", |
||
1930 | attrs.Width, attrs.Height); |
||
1931 | goto cleanup_img; |
||
1932 | } |
||
1933 | |||
1934 | switch (attrs.DRMBufferFormatMESA) { |
||
1935 | case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: |
||
1936 | format = __DRI_IMAGE_FORMAT_ARGB8888; |
||
1937 | break; |
||
1938 | default: |
||
1939 | _eglLog(_EGL_WARNING, "bad image format value 0x%04x", |
||
1940 | attrs.DRMBufferFormatMESA); |
||
1941 | goto cleanup_img; |
||
1942 | } |
||
1943 | |||
1944 | valid_mask = |
||
1945 | EGL_DRM_BUFFER_USE_SCANOUT_MESA | |
||
1946 | EGL_DRM_BUFFER_USE_SHARE_MESA | |
||
1947 | EGL_DRM_BUFFER_USE_CURSOR_MESA; |
||
1948 | if (attrs.DRMBufferUseMESA & ~valid_mask) { |
||
1949 | _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", |
||
1950 | attrs.DRMBufferUseMESA & ~valid_mask); |
||
1951 | goto cleanup_img; |
||
1952 | } |
||
1953 | |||
1954 | dri_use = 0; |
||
1955 | if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA) |
||
1956 | dri_use |= __DRI_IMAGE_USE_SHARE; |
||
1957 | if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) |
||
1958 | dri_use |= __DRI_IMAGE_USE_SCANOUT; |
||
1959 | if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) |
||
1960 | dri_use |= __DRI_IMAGE_USE_CURSOR; |
||
1961 | |||
1962 | dri2_img->dri_image = |
||
1963 | dri2_dpy->image->createImage(dri2_dpy->dri_screen, |
||
1964 | attrs.Width, attrs.Height, |
||
1965 | format, dri_use, dri2_img); |
||
1966 | if (dri2_img->dri_image == NULL) { |
||
1967 | err = EGL_BAD_ALLOC; |
||
1968 | goto cleanup_img; |
||
1969 | } |
||
1970 | |||
1971 | return &dri2_img->base; |
||
1972 | |||
1973 | cleanup_img: |
||
1974 | free(dri2_img); |
||
1975 | _eglError(err, "dri2_create_drm_image_mesa"); |
||
1976 | |||
1977 | return EGL_NO_IMAGE_KHR; |
||
1978 | } |
||
1979 | |||
1980 | static EGLBoolean |
||
1981 | dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, |
||
1982 | EGLint *name, EGLint *handle, EGLint *stride) |
||
1983 | { |
||
1984 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
1985 | struct dri2_egl_image *dri2_img = dri2_egl_image(img); |
||
1986 | |||
1987 | (void) drv; |
||
1988 | |||
1989 | if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image, |
||
1990 | __DRI_IMAGE_ATTRIB_NAME, name)) { |
||
1991 | _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa"); |
||
1992 | return EGL_FALSE; |
||
1993 | } |
||
1994 | |||
1995 | if (handle) |
||
1996 | dri2_dpy->image->queryImage(dri2_img->dri_image, |
||
1997 | __DRI_IMAGE_ATTRIB_HANDLE, handle); |
||
1998 | |||
1999 | if (stride) |
||
2000 | dri2_dpy->image->queryImage(dri2_img->dri_image, |
||
2001 | __DRI_IMAGE_ATTRIB_STRIDE, stride); |
||
2002 | |||
2003 | return EGL_TRUE; |
||
2004 | } |
||
2005 | |||
2006 | static EGLBoolean |
||
2007 | dri2_export_dma_buf_image_query_mesa(_EGLDriver *drv, _EGLDisplay *disp, |
||
2008 | _EGLImage *img, |
||
2009 | EGLint *fourcc, EGLint *nplanes, |
||
2010 | EGLuint64KHR *modifiers) |
||
2011 | { |
||
2012 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
2013 | struct dri2_egl_image *dri2_img = dri2_egl_image(img); |
||
2014 | |||
2015 | (void) drv; |
||
2016 | |||
2017 | |||
2018 | if (nplanes) |
||
2019 | dri2_dpy->image->queryImage(dri2_img->dri_image, |
||
2020 | __DRI_IMAGE_ATTRIB_NUM_PLANES, nplanes); |
||
2021 | if (fourcc) |
||
2022 | dri2_dpy->image->queryImage(dri2_img->dri_image, |
||
2023 | __DRI_IMAGE_ATTRIB_FOURCC, fourcc); |
||
2024 | |||
2025 | if (modifiers) |
||
2026 | *modifiers = 0; |
||
2027 | |||
2028 | return EGL_TRUE; |
||
2029 | } |
||
2030 | |||
2031 | static EGLBoolean |
||
2032 | dri2_export_dma_buf_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, |
||
2033 | int *fds, EGLint *strides, EGLint *offsets) |
||
2034 | { |
||
2035 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
2036 | struct dri2_egl_image *dri2_img = dri2_egl_image(img); |
||
2037 | |||
2038 | (void) drv; |
||
2039 | |||
2040 | /* rework later to provide multiple fds/strides/offsets */ |
||
2041 | if (fds) |
||
2042 | dri2_dpy->image->queryImage(dri2_img->dri_image, |
||
2043 | __DRI_IMAGE_ATTRIB_FD, fds); |
||
2044 | |||
2045 | if (strides) |
||
2046 | dri2_dpy->image->queryImage(dri2_img->dri_image, |
||
2047 | __DRI_IMAGE_ATTRIB_STRIDE, strides); |
||
2048 | |||
2049 | if (offsets) |
||
2050 | offsets[0] = 0; |
||
2051 | |||
2052 | return EGL_TRUE; |
||
2053 | } |
||
2054 | #endif |
||
2055 | |||
2056 | #ifdef HAVE_WAYLAND_PLATFORM |
||
2057 | |||
2058 | static void |
||
2059 | dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd, |
||
2060 | struct wl_drm_buffer *buffer) |
||
2061 | { |
||
2062 | _EGLDisplay *disp = user_data; |
||
2063 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
2064 | __DRIimage *img; |
||
2065 | int i, dri_components = 0; |
||
2066 | |||
2067 | if (fd == -1) |
||
2068 | img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen, |
||
2069 | buffer->width, |
||
2070 | buffer->height, |
||
2071 | buffer->format, |
||
2072 | (int*)&name, 1, |
||
2073 | buffer->stride, |
||
2074 | buffer->offset, |
||
2075 | NULL); |
||
2076 | else |
||
2077 | img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen, |
||
2078 | buffer->width, |
||
2079 | buffer->height, |
||
2080 | buffer->format, |
||
2081 | &fd, 1, |
||
2082 | buffer->stride, |
||
2083 | buffer->offset, |
||
2084 | NULL); |
||
2085 | |||
2086 | if (img == NULL) |
||
2087 | return; |
||
2088 | |||
2089 | dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components); |
||
2090 | |||
2091 | buffer->driver_format = NULL; |
||
2092 | for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++) |
||
2093 | if (wl_drm_components[i].dri_components == dri_components) |
||
2094 | buffer->driver_format = &wl_drm_components[i]; |
||
2095 | |||
2096 | if (buffer->driver_format == NULL) |
||
2097 | dri2_dpy->image->destroyImage(img); |
||
2098 | else |
||
2099 | buffer->driver_buffer = img; |
||
2100 | } |
||
2101 | |||
2102 | static void |
||
2103 | dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer) |
||
2104 | { |
||
2105 | _EGLDisplay *disp = user_data; |
||
2106 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
2107 | |||
2108 | dri2_dpy->image->destroyImage(buffer->driver_buffer); |
||
2109 | } |
||
2110 | |||
2111 | static struct wayland_drm_callbacks wl_drm_callbacks = { |
||
2112 | .authenticate = NULL, |
||
2113 | .reference_buffer = dri2_wl_reference_buffer, |
||
2114 | .release_buffer = dri2_wl_release_buffer |
||
2115 | }; |
||
2116 | |||
2117 | static EGLBoolean |
||
2118 | dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, |
||
2119 | struct wl_display *wl_dpy) |
||
2120 | { |
||
2121 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
2122 | int flags = 0; |
||
2123 | uint64_t cap; |
||
2124 | |||
2125 | (void) drv; |
||
2126 | |||
2127 | if (dri2_dpy->wl_server_drm) |
||
2128 | return EGL_FALSE; |
||
2129 | |||
2130 | wl_drm_callbacks.authenticate = |
||
2131 | (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate; |
||
2132 | |||
2133 | #ifdef HAVE_LIBDRM |
||
2134 | if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 && |
||
2135 | cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) && |
||
2136 | dri2_dpy->image->base.version >= 7 && |
||
2137 | dri2_dpy->image->createImageFromFds != NULL) |
||
2138 | flags |= WAYLAND_DRM_PRIME; |
||
2139 | #endif |
||
2140 | |||
2141 | dri2_dpy->wl_server_drm = |
||
2142 | wayland_drm_init(wl_dpy, dri2_dpy->device_name, |
||
2143 | &wl_drm_callbacks, disp, flags); |
||
2144 | |||
2145 | if (!dri2_dpy->wl_server_drm) |
||
2146 | return EGL_FALSE; |
||
2147 | |||
2148 | #ifdef HAVE_DRM_PLATFORM |
||
2149 | /* We have to share the wl_drm instance with gbm, so gbm can convert |
||
2150 | * wl_buffers to gbm bos. */ |
||
2151 | if (dri2_dpy->gbm_dri) |
||
2152 | dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm; |
||
2153 | #endif |
||
2154 | |||
2155 | return EGL_TRUE; |
||
2156 | } |
||
2157 | |||
2158 | static EGLBoolean |
||
2159 | dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, |
||
2160 | struct wl_display *wl_dpy) |
||
2161 | { |
||
2162 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
2163 | |||
2164 | (void) drv; |
||
2165 | |||
2166 | if (!dri2_dpy->wl_server_drm) |
||
2167 | return EGL_FALSE; |
||
2168 | |||
2169 | wayland_drm_uninit(dri2_dpy->wl_server_drm); |
||
2170 | dri2_dpy->wl_server_drm = NULL; |
||
2171 | |||
2172 | return EGL_TRUE; |
||
2173 | } |
||
2174 | |||
2175 | static EGLBoolean |
||
2176 | dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp, |
||
2177 | struct wl_resource *buffer_resource, |
||
2178 | EGLint attribute, EGLint *value) |
||
2179 | { |
||
2180 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); |
||
2181 | struct wl_drm_buffer *buffer; |
||
2182 | const struct wl_drm_components_descriptor *format; |
||
2183 | |||
2184 | buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource); |
||
2185 | if (!buffer) |
||
2186 | return EGL_FALSE; |
||
2187 | |||
2188 | format = buffer->driver_format; |
||
2189 | switch (attribute) { |
||
2190 | case EGL_TEXTURE_FORMAT: |
||
2191 | *value = format->components; |
||
2192 | return EGL_TRUE; |
||
2193 | case EGL_WIDTH: |
||
2194 | *value = buffer->width; |
||
2195 | return EGL_TRUE; |
||
2196 | case EGL_HEIGHT: |
||
2197 | *value = buffer->height; |
||
2198 | return EGL_TRUE; |
||
2199 | } |
||
2200 | |||
2201 | return EGL_FALSE; |
||
2202 | } |
||
2203 | #endif |
||
2204 | |||
2205 | static void |
||
2206 | dri2_egl_ref_sync(struct dri2_egl_sync *sync) |
||
2207 | { |
||
2208 | p_atomic_inc(&sync->refcount); |
||
2209 | } |
||
2210 | |||
2211 | static void |
||
2212 | dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy, |
||
2213 | struct dri2_egl_sync *dri2_sync) |
||
2214 | { |
||
2215 | if (p_atomic_dec_zero(&dri2_sync->refcount)) { |
||
2216 | dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence); |
||
2217 | free(dri2_sync); |
||
2218 | } |
||
2219 | } |
||
2220 | |||
2221 | static _EGLSync * |
||
2222 | dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy, |
||
2223 | EGLenum type, const EGLint *attrib_list, |
||
2224 | const EGLAttribKHR *attrib_list64) |
||
2225 | { |
||
2226 | _EGLContext *ctx = _eglGetCurrentContext(); |
||
2227 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
2228 | struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); |
||
2229 | struct dri2_egl_sync *dri2_sync; |
||
2230 | |||
2231 | dri2_sync = calloc(1, sizeof(struct dri2_egl_sync)); |
||
2232 | if (!dri2_sync) { |
||
2233 | _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); |
||
2234 | return NULL; |
||
2235 | } |
||
2236 | |||
2237 | if (!_eglInitSync(&dri2_sync->base, dpy, type, attrib_list, |
||
2238 | attrib_list64)) { |
||
2239 | free(dri2_sync); |
||
2240 | return NULL; |
||
2241 | } |
||
2242 | |||
2243 | switch (type) { |
||
2244 | case EGL_SYNC_FENCE_KHR: |
||
2245 | dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context); |
||
2246 | if (!dri2_sync->fence) { |
||
2247 | /* Why did it fail? DRI doesn't return an error code, so we emit |
||
2248 | * a generic EGL error that doesn't communicate user error. |
||
2249 | */ |
||
2250 | _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); |
||
2251 | free(dri2_sync); |
||
2252 | return NULL; |
||
2253 | } |
||
2254 | break; |
||
2255 | |||
2256 | case EGL_SYNC_CL_EVENT_KHR: |
||
2257 | dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event( |
||
2258 | dri2_dpy->dri_screen, |
||
2259 | dri2_sync->base.CLEvent); |
||
2260 | /* this can only happen if the cl_event passed in is invalid. */ |
||
2261 | if (!dri2_sync->fence) { |
||
2262 | _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR"); |
||
2263 | free(dri2_sync); |
||
2264 | return NULL; |
||
2265 | } |
||
2266 | |||
2267 | /* the initial status must be "signaled" if the cl_event is signaled */ |
||
2268 | if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context, |
||
2269 | dri2_sync->fence, 0, 0)) |
||
2270 | dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; |
||
2271 | break; |
||
2272 | } |
||
2273 | |||
2274 | p_atomic_set(&dri2_sync->refcount, 1); |
||
2275 | return &dri2_sync->base; |
||
2276 | } |
||
2277 | |||
2278 | static EGLBoolean |
||
2279 | dri2_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync) |
||
2280 | { |
||
2281 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
2282 | struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); |
||
2283 | |||
2284 | dri2_egl_unref_sync(dri2_dpy, dri2_sync); |
||
2285 | return EGL_TRUE; |
||
2286 | } |
||
2287 | |||
2288 | static EGLint |
||
2289 | dri2_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, |
||
2290 | EGLint flags, EGLTimeKHR timeout) |
||
2291 | { |
||
2292 | _EGLContext *ctx = _eglGetCurrentContext(); |
||
2293 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
2294 | struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); |
||
2295 | struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); |
||
2296 | unsigned wait_flags = 0; |
||
2297 | EGLint ret = EGL_CONDITION_SATISFIED_KHR; |
||
2298 | |||
2299 | if (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) |
||
2300 | wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS; |
||
2301 | |||
2302 | /* the sync object should take a reference while waiting */ |
||
2303 | dri2_egl_ref_sync(dri2_sync); |
||
2304 | |||
2305 | if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context, |
||
2306 | dri2_sync->fence, wait_flags, |
||
2307 | timeout)) |
||
2308 | dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; |
||
2309 | else |
||
2310 | ret = EGL_TIMEOUT_EXPIRED_KHR; |
||
2311 | |||
2312 | dri2_egl_unref_sync(dri2_dpy, dri2_sync); |
||
2313 | return ret; |
||
2314 | } |
||
2315 | |||
2316 | static EGLint |
||
2317 | dri2_server_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync) |
||
2318 | { |
||
2319 | _EGLContext *ctx = _eglGetCurrentContext(); |
||
2320 | struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); |
||
2321 | struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); |
||
2322 | struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); |
||
2323 | |||
2324 | dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context, |
||
2325 | dri2_sync->fence, 0); |
||
2326 | return EGL_TRUE; |
||
2327 | } |
||
2328 | |||
2329 | static void |
||
2330 | dri2_unload(_EGLDriver *drv) |
||
2331 | { |
||
2332 | struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); |
||
2333 | |||
2334 | if (dri2_drv->handle) |
||
2335 | dlclose(dri2_drv->handle); |
||
2336 | free(dri2_drv); |
||
2337 | } |
||
2338 | |||
2339 | static EGLBoolean |
||
2340 | dri2_load(_EGLDriver *drv) |
||
2341 | { |
||
2342 | struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); |
||
2343 | #ifdef HAVE_SHARED_GLAPI |
||
2344 | #ifdef HAVE_ANDROID_PLATFORM |
||
2345 | const char *libname = "libglapi.so"; |
||
2346 | #else |
||
2347 | const char *libname = "libglapi.so.0"; |
||
2348 | #endif |
||
2349 | #else |
||
2350 | /* |
||
2351 | * Both libGL.so and libglapi.so are glapi providers. There is no way to |
||
2352 | * tell which one to load. |
||
2353 | */ |
||
2354 | const char *libname = NULL; |
||
2355 | #endif |
||
2356 | void *handle; |
||
2357 | |||
2358 | /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */ |
||
2359 | handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); |
||
2360 | if (handle) { |
||
2361 | dri2_drv->get_proc_address = (_EGLProc (*)(const char *)) |
||
2362 | dlsym(handle, "_glapi_get_proc_address"); |
||
2363 | if (!dri2_drv->get_proc_address || !libname) { |
||
2364 | /* no need to keep a reference */ |
||
2365 | dlclose(handle); |
||
2366 | handle = NULL; |
||
2367 | } |
||
2368 | } |
||
2369 | |||
2370 | /* if glapi is not available, loading DRI drivers will fail */ |
||
2371 | if (!dri2_drv->get_proc_address) { |
||
2372 | _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address"); |
||
2373 | return EGL_FALSE; |
||
2374 | } |
||
2375 | |||
2376 | dri2_drv->glFlush = (void (*)(void)) |
||
2377 | dri2_drv->get_proc_address("glFlush"); |
||
2378 | |||
2379 | dri2_drv->handle = handle; |
||
2380 | |||
2381 | return EGL_TRUE; |
||
2382 | } |
||
2383 | |||
2384 | /** |
||
2385 | * This is the main entrypoint into the driver, called by libEGL. |
||
2386 | * Create a new _EGLDriver object and init its dispatch table. |
||
2387 | */ |
||
2388 | _EGLDriver * |
||
2389 | _eglBuiltInDriverDRI2(const char *args) |
||
2390 | { |
||
2391 | struct dri2_egl_driver *dri2_drv; |
||
2392 | |||
2393 | (void) args; |
||
2394 | |||
2395 | dri2_drv = calloc(1, sizeof *dri2_drv); |
||
2396 | if (!dri2_drv) |
||
2397 | return NULL; |
||
2398 | |||
2399 | if (!dri2_load(&dri2_drv->base)) { |
||
2400 | free(dri2_drv); |
||
2401 | return NULL; |
||
2402 | } |
||
2403 | |||
2404 | _eglInitDriverFallbacks(&dri2_drv->base); |
||
2405 | dri2_drv->base.API.Initialize = dri2_initialize; |
||
2406 | dri2_drv->base.API.Terminate = dri2_terminate; |
||
2407 | dri2_drv->base.API.CreateContext = dri2_create_context; |
||
2408 | dri2_drv->base.API.DestroyContext = dri2_destroy_context; |
||
2409 | dri2_drv->base.API.MakeCurrent = dri2_make_current; |
||
2410 | dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface; |
||
2411 | dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface; |
||
2412 | dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface; |
||
2413 | dri2_drv->base.API.DestroySurface = dri2_destroy_surface; |
||
2414 | dri2_drv->base.API.GetProcAddress = dri2_get_proc_address; |
||
2415 | dri2_drv->base.API.WaitClient = dri2_wait_client; |
||
2416 | dri2_drv->base.API.WaitNative = dri2_wait_native; |
||
2417 | dri2_drv->base.API.BindTexImage = dri2_bind_tex_image; |
||
2418 | dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image; |
||
2419 | dri2_drv->base.API.SwapInterval = dri2_swap_interval; |
||
2420 | dri2_drv->base.API.SwapBuffers = dri2_swap_buffers; |
||
2421 | dri2_drv->base.API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage; |
||
2422 | dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region; |
||
2423 | dri2_drv->base.API.PostSubBufferNV = dri2_post_sub_buffer; |
||
2424 | dri2_drv->base.API.CopyBuffers = dri2_copy_buffers, |
||
2425 | dri2_drv->base.API.QueryBufferAge = dri2_query_buffer_age; |
||
2426 | dri2_drv->base.API.CreateImageKHR = dri2_create_image; |
||
2427 | dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr; |
||
2428 | dri2_drv->base.API.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image; |
||
2429 | #ifdef HAVE_LIBDRM |
||
2430 | dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa; |
||
2431 | dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa; |
||
2432 | dri2_drv->base.API.ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa; |
||
2433 | dri2_drv->base.API.ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa; |
||
2434 | #endif |
||
2435 | #ifdef HAVE_WAYLAND_PLATFORM |
||
2436 | dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl; |
||
2437 | dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl; |
||
2438 | dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl; |
||
2439 | #endif |
||
2440 | dri2_drv->base.API.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium; |
||
2441 | dri2_drv->base.API.CreateSyncKHR = dri2_create_sync; |
||
2442 | dri2_drv->base.API.ClientWaitSyncKHR = dri2_client_wait_sync; |
||
2443 | dri2_drv->base.API.WaitSyncKHR = dri2_server_wait_sync; |
||
2444 | dri2_drv->base.API.DestroySyncKHR = dri2_destroy_sync; |
||
2445 | |||
2446 | dri2_drv->base.Name = "DRI2"; |
||
2447 | dri2_drv->base.Unload = dri2_unload; |
||
2448 | |||
2449 | return &dri2_drv->base; |
||
2450 | }>=>=>>>>=>>=>=>>=>=>=>=>><>><> |