Merge branch '7.8'
[mesa.git] / src / gallium / state_trackers / egl / common / egl_g3d.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.8
4 *
5 * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "egldriver.h"
27 #include "eglcurrent.h"
28 #include "egllog.h"
29
30 #include "pipe/p_screen.h"
31 #include "util/u_memory.h"
32 #include "util/u_format.h"
33 #include "util/u_string.h"
34
35 #include "egl_g3d.h"
36 #include "egl_g3d_api.h"
37 #include "egl_g3d_st.h"
38 #include "native.h"
39
40 /**
41 * Initialize the state trackers.
42 */
43 static void
44 egl_g3d_init_st(_EGLDriver *drv)
45 {
46 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
47 EGLint i;
48
49 /* already initialized */
50 if (gdrv->api_mask)
51 return;
52
53 for (i = 0; i < ST_API_COUNT; i++) {
54 gdrv->stapis[i] = egl_g3d_create_st_api(i);
55 if (gdrv->stapis[i])
56 gdrv->api_mask |= egl_g3d_st_api_bit(i);
57 }
58
59 if (gdrv->api_mask)
60 _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask);
61 else
62 _eglLog(_EGL_WARNING, "No supported client API");
63 }
64
65 /**
66 * Get the probe object of the display.
67 *
68 * Note that this function may be called before the display is initialized.
69 */
70 static struct native_probe *
71 egl_g3d_get_probe(_EGLDriver *drv, _EGLDisplay *dpy)
72 {
73 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
74 struct native_probe *nprobe;
75
76 nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
77 if (!nprobe || nprobe->display != dpy->NativeDisplay) {
78 if (nprobe)
79 nprobe->destroy(nprobe);
80 nprobe = native_create_probe(dpy->NativeDisplay);
81 _eglSetProbeCache(gdrv->probe_key, (void *) nprobe);
82 }
83
84 return nprobe;
85 }
86
87 /**
88 * Destroy the probe object of the display. The display may be NULL.
89 *
90 * Note that this function may be called before the display is initialized.
91 */
92 static void
93 egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy)
94 {
95 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
96 struct native_probe *nprobe;
97
98 nprobe = (struct native_probe *) _eglGetProbeCache(gdrv->probe_key);
99 if (nprobe && (!dpy || nprobe->display == dpy->NativeDisplay)) {
100 nprobe->destroy(nprobe);
101 _eglSetProbeCache(gdrv->probe_key, NULL);
102 }
103 }
104
105 #ifdef EGL_MESA_screen_surface
106
107 static void
108 egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
109 {
110 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
111 const struct native_connector **native_connectors;
112 EGLint num_connectors, i;
113
114 native_connectors =
115 gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
116 if (!num_connectors) {
117 if (native_connectors)
118 FREE(native_connectors);
119 return;
120 }
121
122 for (i = 0; i < num_connectors; i++) {
123 const struct native_connector *nconn = native_connectors[i];
124 struct egl_g3d_screen *gscr;
125 const struct native_mode **native_modes;
126 EGLint num_modes, j;
127
128 /* TODO support for hotplug */
129 native_modes =
130 gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
131 if (!num_modes) {
132 if (native_modes)
133 FREE(native_modes);
134 continue;
135 }
136
137 gscr = CALLOC_STRUCT(egl_g3d_screen);
138 if (!gscr) {
139 FREE(native_modes);
140 continue;
141 }
142
143 _eglInitScreen(&gscr->base);
144
145 for (j = 0; j < num_modes; j++) {
146 const struct native_mode *nmode = native_modes[j];
147 _EGLMode *mode;
148
149 mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height,
150 nmode->refresh_rate, nmode->desc);
151 if (!mode)
152 break;
153 /* gscr->native_modes and gscr->base.Modes should be consistent */
154 assert(mode == &gscr->base.Modes[j]);
155 }
156
157 gscr->native = nconn;
158 gscr->native_modes = native_modes;
159
160 _eglAddScreen(dpy, &gscr->base);
161 }
162
163 FREE(native_connectors);
164 }
165
166 #endif /* EGL_MESA_screen_surface */
167
168 /**
169 * Initialize and validate the EGL config attributes.
170 */
171 static EGLBoolean
172 init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
173 EGLint api_mask, enum pipe_format depth_stencil_format)
174 {
175 uint rgba[4], depth_stencil[2], buffer_size;
176 EGLint surface_type;
177 EGLint i;
178
179 /* get the color and depth/stencil component sizes */
180 assert(nconf->color_format != PIPE_FORMAT_NONE);
181 buffer_size = 0;
182 for (i = 0; i < 4; i++) {
183 rgba[i] = util_format_get_component_bits(nconf->color_format,
184 UTIL_FORMAT_COLORSPACE_RGB, i);
185 buffer_size += rgba[i];
186 }
187 for (i = 0; i < 2; i++) {
188 if (depth_stencil_format != PIPE_FORMAT_NONE) {
189 depth_stencil[i] =
190 util_format_get_component_bits(depth_stencil_format,
191 UTIL_FORMAT_COLORSPACE_ZS, i);
192 }
193 else {
194 depth_stencil[i] = 0;
195 }
196 }
197
198 surface_type = 0x0;
199 if (nconf->window_bit)
200 surface_type |= EGL_WINDOW_BIT;
201 if (nconf->pixmap_bit)
202 surface_type |= EGL_PIXMAP_BIT;
203 #ifdef EGL_MESA_screen_surface
204 if (nconf->scanout_bit)
205 surface_type |= EGL_SCREEN_BIT_MESA;
206 #endif
207
208 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
209 surface_type |= EGL_PBUFFER_BIT;
210
211 SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, api_mask);
212 SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, api_mask);
213
214 SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, rgba[0]);
215 SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, rgba[1]);
216 SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, rgba[2]);
217 SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, rgba[3]);
218 SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, buffer_size);
219
220 SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, depth_stencil[0]);
221 SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, depth_stencil[1]);
222
223 SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type);
224
225 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_TRUE);
226 if (surface_type & EGL_WINDOW_BIT) {
227 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, nconf->native_visual_id);
228 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE,
229 nconf->native_visual_type);
230 }
231
232 if (surface_type & EGL_PBUFFER_BIT) {
233 SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
234 if (rgba[3])
235 SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
236
237 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, 4096);
238 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, 4096);
239 SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, 4096 * 4096);
240 }
241
242 SET_CONFIG_ATTRIB(conf, EGL_LEVEL, nconf->level);
243 SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, nconf->samples);
244 SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, 1);
245
246 if (nconf->slow_config)
247 SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG);
248
249 if (nconf->transparent_rgb) {
250 rgba[0] = nconf->transparent_rgb_values[0];
251 rgba[1] = nconf->transparent_rgb_values[1];
252 rgba[2] = nconf->transparent_rgb_values[2];
253
254 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB);
255 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, rgba[0]);
256 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, rgba[1]);
257 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, rgba[2]);
258 }
259
260 return _eglValidateConfig(conf, EGL_FALSE);
261 }
262
263 /**
264 * Initialize an EGL config from the native config.
265 */
266 static EGLBoolean
267 egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
268 _EGLConfig *conf, const struct native_config *nconf,
269 enum pipe_format depth_stencil_format)
270 {
271 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
272 struct egl_g3d_config *gconf = egl_g3d_config(conf);
273 EGLint buffer_mask, api_mask;
274 EGLBoolean valid;
275 EGLint i;
276
277 buffer_mask = 0x0;
278 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT))
279 buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
280 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
281 buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
282 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT))
283 buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
284 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT))
285 buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
286
287 gconf->stvis.buffer_mask = buffer_mask;
288 gconf->stvis.color_format = nconf->color_format;
289 gconf->stvis.depth_stencil_format = depth_stencil_format;
290 gconf->stvis.accum_format = PIPE_FORMAT_NONE;
291 gconf->stvis.samples = nconf->samples;
292
293 gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
294 ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
295
296 api_mask = 0;
297 for (i = 0; i < ST_API_COUNT; i++) {
298 struct st_api *stapi = gdrv->stapis[i];
299 if (stapi) {
300 if (stapi->is_visual_supported(stapi, &gconf->stvis))
301 api_mask |= egl_g3d_st_api_bit(i);
302 }
303 }
304 /* this is required by EGL, not by OpenGL ES */
305 if (nconf->window_bit &&
306 gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT)
307 api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
308
309 if (!api_mask) {
310 _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
311 nconf->native_visual_id);
312 }
313
314 valid = init_config_attributes(&gconf->base,
315 nconf, api_mask, depth_stencil_format);
316 if (!valid) {
317 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
318 return EGL_FALSE;
319 }
320
321 gconf->native = nconf;
322
323 return EGL_TRUE;
324 }
325
326 /**
327 * Get all interested depth/stencil formats of a display.
328 */
329 static EGLint
330 egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
331 enum pipe_format formats[8])
332 {
333 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
334 struct pipe_screen *screen = gdpy->native->screen;
335 const EGLint candidates[] = {
336 1, PIPE_FORMAT_Z16_UNORM,
337 1, PIPE_FORMAT_Z32_UNORM,
338 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
339 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
340 0
341 };
342 const EGLint *fmt = candidates;
343 EGLint count;
344
345 count = 0;
346 formats[count++] = PIPE_FORMAT_NONE;
347
348 while (*fmt) {
349 EGLint i, n = *fmt++;
350
351 /* pick the first supported format */
352 for (i = 0; i < n; i++) {
353 if (screen->is_format_supported(screen, fmt[i],
354 PIPE_TEXTURE_2D, PIPE_BIND_DEPTH_STENCIL, 0)) {
355 formats[count++] = fmt[i];
356 break;
357 }
358 }
359
360 fmt += n;
361 }
362
363 return count;
364 }
365
366 /**
367 * Add configs to display and return the next config ID.
368 */
369 static EGLint
370 egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
371 {
372 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
373 const struct native_config **native_configs;
374 enum pipe_format depth_stencil_formats[8];
375 int num_formats, num_configs, i, j;
376
377 native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
378 if (!num_configs) {
379 if (native_configs)
380 FREE(native_configs);
381 return id;
382 }
383
384 num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
385 depth_stencil_formats);
386
387 for (i = 0; i < num_configs; i++) {
388 for (j = 0; j < num_formats; j++) {
389 struct egl_g3d_config *gconf;
390
391 gconf = CALLOC_STRUCT(egl_g3d_config);
392 if (gconf) {
393 _eglInitConfig(&gconf->base, dpy, id);
394 if (!egl_g3d_init_config(drv, dpy, &gconf->base,
395 native_configs[i], depth_stencil_formats[j])) {
396 FREE(gconf);
397 break;
398 }
399
400 _eglAddConfig(dpy, &gconf->base);
401 id++;
402 }
403 }
404 }
405
406 FREE(native_configs);
407 return id;
408 }
409
410 static void
411 egl_g3d_invalid_surface(struct native_display *ndpy,
412 struct native_surface *nsurf,
413 unsigned int seq_num)
414 {
415 /* XXX not thread safe? */
416 struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
417 struct egl_g3d_context *gctx;
418
419 /*
420 * Some functions such as egl_g3d_copy_buffers create a temporary native
421 * surface. There is no gsurf associated with it.
422 */
423 gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
424 if (gctx)
425 gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
426 }
427
428 static struct native_event_handler egl_g3d_native_event_handler = {
429 .invalid_surface = egl_g3d_invalid_surface
430 };
431
432 static EGLBoolean
433 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
434 {
435 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
436 EGLint i;
437
438 _eglReleaseDisplayResources(drv, dpy);
439 _eglCleanupDisplay(dpy);
440
441 if (gdpy->pipe)
442 gdpy->pipe->destroy(gdpy->pipe);
443
444 if (dpy->Screens) {
445 for (i = 0; i < dpy->NumScreens; i++) {
446 struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]);
447 FREE(gscr->native_modes);
448 FREE(gscr);
449 }
450 FREE(dpy->Screens);
451 }
452
453 if (gdpy->smapi)
454 egl_g3d_destroy_st_manager(gdpy->smapi);
455
456 if (gdpy->native)
457 gdpy->native->destroy(gdpy->native);
458
459 FREE(gdpy);
460 dpy->DriverData = NULL;
461
462 return EGL_TRUE;
463 }
464
465 static EGLBoolean
466 egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
467 EGLint *major, EGLint *minor)
468 {
469 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
470 struct egl_g3d_display *gdpy;
471
472 /* the probe object is unlikely to be needed again */
473 egl_g3d_destroy_probe(drv, dpy);
474
475 gdpy = CALLOC_STRUCT(egl_g3d_display);
476 if (!gdpy) {
477 _eglError(EGL_BAD_ALLOC, "eglInitialize");
478 goto fail;
479 }
480 dpy->DriverData = gdpy;
481
482 gdpy->native = native_create_display(dpy->NativeDisplay,
483 &egl_g3d_native_event_handler);
484 if (!gdpy->native) {
485 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
486 goto fail;
487 }
488
489 gdpy->native->user_data = (void *) dpy;
490
491 egl_g3d_init_st(&gdrv->base);
492 dpy->ClientAPIsMask = gdrv->api_mask;
493
494 gdpy->smapi = egl_g3d_create_st_manager(dpy);
495 if (!gdpy->smapi) {
496 _eglError(EGL_NOT_INITIALIZED,
497 "eglInitialize(failed to create st manager)");
498 goto fail;
499 }
500
501 #ifdef EGL_MESA_screen_surface
502 /* enable MESA_screen_surface before adding (and validating) configs */
503 if (gdpy->native->modeset) {
504 dpy->Extensions.MESA_screen_surface = EGL_TRUE;
505 egl_g3d_add_screens(drv, dpy);
506 }
507 #endif
508
509 dpy->Extensions.KHR_image_base = EGL_TRUE;
510 if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
511 dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
512
513 if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
514 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
515 goto fail;
516 }
517
518 *major = 1;
519 *minor = 4;
520
521 return EGL_TRUE;
522
523 fail:
524 if (gdpy)
525 egl_g3d_terminate(drv, dpy);
526 return EGL_FALSE;
527 }
528
529 static _EGLProc
530 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
531 {
532 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
533 _EGLProc proc;
534 EGLint i;
535
536 /* in case this is called before a display is initialized */
537 egl_g3d_init_st(&gdrv->base);
538
539 for (i = 0; i < ST_API_COUNT; i++) {
540 struct st_api *stapi = gdrv->stapis[i];
541 if (stapi) {
542 proc = (_EGLProc) stapi->get_proc_address(stapi, procname);
543 if (proc)
544 return proc;
545 }
546 }
547
548 return (_EGLProc) NULL;
549 }
550
551 static EGLint
552 egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
553 {
554 struct native_probe *nprobe;
555 enum native_probe_result res;
556 EGLint score;
557
558 nprobe = egl_g3d_get_probe(drv, dpy);
559 res = native_get_probe_result(nprobe);
560
561 switch (res) {
562 case NATIVE_PROBE_UNKNOWN:
563 default:
564 score = 0;
565 break;
566 case NATIVE_PROBE_FALLBACK:
567 score = 40;
568 break;
569 case NATIVE_PROBE_SUPPORTED:
570 score = 50;
571 break;
572 case NATIVE_PROBE_EXACT:
573 score = 100;
574 break;
575 }
576
577 return score;
578 }
579
580 static void
581 egl_g3d_unload(_EGLDriver *drv)
582 {
583 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
584 EGLint i;
585
586 for (i = 0; i < ST_API_COUNT; i++) {
587 if (gdrv->stapis[i])
588 gdrv->stapis[i]->destroy(gdrv->stapis[i]);
589 }
590
591 egl_g3d_destroy_probe(drv, NULL);
592 FREE(gdrv);
593 }
594
595 _EGLDriver *
596 _eglMain(const char *args)
597 {
598 static char driver_name[64];
599 struct egl_g3d_driver *gdrv;
600
601 util_snprintf(driver_name, sizeof(driver_name),
602 "Gallium/%s", native_get_name());
603
604 gdrv = CALLOC_STRUCT(egl_g3d_driver);
605 if (!gdrv)
606 return NULL;
607
608 egl_g3d_init_driver_api(&gdrv->base);
609 gdrv->base.API.Initialize = egl_g3d_initialize;
610 gdrv->base.API.Terminate = egl_g3d_terminate;
611 gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
612
613 gdrv->base.Name = driver_name;
614 gdrv->base.Probe = egl_g3d_probe;
615 gdrv->base.Unload = egl_g3d_unload;
616
617 /* the key is " EGL G3D" */
618 gdrv->probe_key = 0x0E61063D;
619
620 return &gdrv->base;
621 }