Merge remote branch 'origin/master' into pipe-video
[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 "egl_g3d_loader.h"
39 #include "native.h"
40
41 /**
42 * Get the native platform.
43 */
44 static const struct native_platform *
45 egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
46 {
47 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
48
49 if (!gdrv->platforms[plat]) {
50 const char *plat_name = NULL;
51 const struct native_platform *nplat = NULL;
52
53 switch (plat) {
54 case _EGL_PLATFORM_WINDOWS:
55 plat_name = "Windows";
56 #ifdef HAVE_GDI_BACKEND
57 nplat = native_get_gdi_platform();
58 #endif
59 break;
60 case _EGL_PLATFORM_X11:
61 plat_name = "X11";
62 #ifdef HAVE_X11_BACKEND
63 nplat = native_get_x11_platform();
64 #endif
65 break;
66 case _EGL_PLATFORM_DRM:
67 plat_name = "DRM";
68 #ifdef HAVE_DRM_BACKEND
69 nplat = native_get_drm_platform();
70 #endif
71 break;
72 case _EGL_PLATFORM_FBDEV:
73 plat_name = "FBDEV";
74 #ifdef HAVE_FBDEV_BACKEND
75 nplat = native_get_fbdev_platform();
76 #endif
77 break;
78 default:
79 break;
80 }
81
82 if (!nplat)
83 _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name);
84
85 gdrv->platforms[plat] = nplat;
86 }
87
88 return gdrv->platforms[plat];
89 }
90
91 #ifdef EGL_MESA_screen_surface
92
93 static void
94 egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
95 {
96 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
97 const struct native_connector **native_connectors;
98 EGLint num_connectors, i;
99
100 native_connectors =
101 gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
102 if (!num_connectors) {
103 if (native_connectors)
104 FREE(native_connectors);
105 return;
106 }
107
108 for (i = 0; i < num_connectors; i++) {
109 const struct native_connector *nconn = native_connectors[i];
110 struct egl_g3d_screen *gscr;
111 const struct native_mode **native_modes;
112 EGLint num_modes, j;
113
114 /* TODO support for hotplug */
115 native_modes =
116 gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
117 if (!num_modes) {
118 if (native_modes)
119 FREE(native_modes);
120 continue;
121 }
122
123 gscr = CALLOC_STRUCT(egl_g3d_screen);
124 if (!gscr) {
125 FREE(native_modes);
126 continue;
127 }
128
129 _eglInitScreen(&gscr->base, dpy, num_modes);
130 for (j = 0; j < gscr->base.NumModes; j++) {
131 const struct native_mode *nmode = native_modes[j];
132 _EGLMode *mode = &gscr->base.Modes[j];
133
134 mode->Width = nmode->width;
135 mode->Height = nmode->height;
136 mode->RefreshRate = nmode->refresh_rate;
137 mode->Optimal = EGL_FALSE;
138 mode->Interlaced = EGL_FALSE;
139 /* no need to strdup() */
140 mode->Name = nmode->desc;
141 }
142
143 gscr->native = nconn;
144 gscr->native_modes = native_modes;
145
146 _eglLinkScreen(&gscr->base);
147 }
148
149 FREE(native_connectors);
150 }
151
152 #endif /* EGL_MESA_screen_surface */
153
154 /**
155 * Initialize and validate the EGL config attributes.
156 */
157 static EGLBoolean
158 init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
159 EGLint api_mask, enum pipe_format depth_stencil_format,
160 EGLBoolean preserve_buffer, EGLint max_swap_interval)
161 {
162 uint rgba[4], depth_stencil[2], buffer_size;
163 EGLint surface_type;
164 EGLint i;
165
166 /* get the color and depth/stencil component sizes */
167 assert(nconf->color_format != PIPE_FORMAT_NONE);
168 buffer_size = 0;
169 for (i = 0; i < 4; i++) {
170 rgba[i] = util_format_get_component_bits(nconf->color_format,
171 UTIL_FORMAT_COLORSPACE_RGB, i);
172 buffer_size += rgba[i];
173 }
174 for (i = 0; i < 2; i++) {
175 if (depth_stencil_format != PIPE_FORMAT_NONE) {
176 depth_stencil[i] =
177 util_format_get_component_bits(depth_stencil_format,
178 UTIL_FORMAT_COLORSPACE_ZS, i);
179 }
180 else {
181 depth_stencil[i] = 0;
182 }
183 }
184
185 surface_type = 0x0;
186 if (nconf->window_bit)
187 surface_type |= EGL_WINDOW_BIT;
188 if (nconf->pixmap_bit)
189 surface_type |= EGL_PIXMAP_BIT;
190 #ifdef EGL_MESA_screen_surface
191 if (nconf->scanout_bit)
192 surface_type |= EGL_SCREEN_BIT_MESA;
193 #endif
194
195 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
196 surface_type |= EGL_PBUFFER_BIT;
197
198 conf->Conformant = api_mask;
199 conf->RenderableType = api_mask;
200
201 conf->RedSize = rgba[0];
202 conf->GreenSize = rgba[1];
203 conf->BlueSize = rgba[2];
204 conf->AlphaSize = rgba[3];
205 conf->BufferSize = buffer_size;
206
207 conf->DepthSize = depth_stencil[0];
208 conf->StencilSize = depth_stencil[1];
209
210 conf->SurfaceType = surface_type;
211
212 conf->NativeRenderable = EGL_TRUE;
213 if (surface_type & EGL_WINDOW_BIT) {
214 conf->NativeVisualID = nconf->native_visual_id;
215 conf->NativeVisualType = nconf->native_visual_type;
216 }
217
218 if (surface_type & EGL_PBUFFER_BIT) {
219 conf->BindToTextureRGB = EGL_TRUE;
220 if (rgba[3])
221 conf->BindToTextureRGBA = EGL_TRUE;
222
223 conf->MaxPbufferWidth = 4096;
224 conf->MaxPbufferHeight = 4096;
225 conf->MaxPbufferPixels = 4096 * 4096;
226 }
227
228 conf->Level = nconf->level;
229 conf->Samples = nconf->samples;
230 conf->SampleBuffers = 0;
231
232 if (nconf->slow_config)
233 conf->ConfigCaveat = EGL_SLOW_CONFIG;
234
235 if (nconf->transparent_rgb) {
236 conf->TransparentType = EGL_TRANSPARENT_RGB;
237 conf->TransparentRedValue = nconf->transparent_rgb_values[0];
238 conf->TransparentGreenValue = nconf->transparent_rgb_values[1];
239 conf->TransparentBlueValue = nconf->transparent_rgb_values[2];
240 }
241
242 conf->MinSwapInterval = 0;
243 conf->MaxSwapInterval = max_swap_interval;
244 if (preserve_buffer)
245 conf->SurfaceType |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
246
247 return _eglValidateConfig(conf, EGL_FALSE);
248 }
249
250 /**
251 * Initialize an EGL config from the native config.
252 */
253 static EGLBoolean
254 egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
255 _EGLConfig *conf, const struct native_config *nconf,
256 enum pipe_format depth_stencil_format,
257 int preserve_buffer, int max_swap_interval)
258 {
259 struct egl_g3d_config *gconf = egl_g3d_config(conf);
260 EGLint buffer_mask, api_mask;
261 EGLBoolean valid;
262
263 /* skip single-buffered configs */
264 if (!(nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)))
265 return EGL_FALSE;
266
267 buffer_mask = 0x0;
268 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT))
269 buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
270 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
271 buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
272 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT))
273 buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
274 if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT))
275 buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
276
277 gconf->stvis.buffer_mask = buffer_mask;
278 gconf->stvis.color_format = nconf->color_format;
279 gconf->stvis.depth_stencil_format = depth_stencil_format;
280 gconf->stvis.accum_format = PIPE_FORMAT_NONE;
281 gconf->stvis.samples = nconf->samples;
282
283 gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
284 ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
285
286 api_mask = dpy->ClientAPIsMask;
287 /* this is required by EGL, not by OpenGL ES */
288 if (nconf->window_bit &&
289 gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT)
290 api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
291
292 if (!api_mask) {
293 _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x",
294 nconf->native_visual_id);
295 }
296
297 valid = init_config_attributes(&gconf->base,
298 nconf, api_mask, depth_stencil_format,
299 preserve_buffer, max_swap_interval);
300 if (!valid) {
301 _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
302 return EGL_FALSE;
303 }
304
305 gconf->native = nconf;
306
307 return EGL_TRUE;
308 }
309
310 /**
311 * Get all interested depth/stencil formats of a display.
312 */
313 static EGLint
314 egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
315 enum pipe_format formats[8])
316 {
317 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
318 struct pipe_screen *screen = gdpy->native->screen;
319 const EGLint candidates[] = {
320 1, PIPE_FORMAT_Z16_UNORM,
321 1, PIPE_FORMAT_Z32_UNORM,
322 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
323 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
324 0
325 };
326 const EGLint *fmt = candidates;
327 EGLint count;
328
329 count = 0;
330 formats[count++] = PIPE_FORMAT_NONE;
331
332 while (*fmt) {
333 EGLint i, n = *fmt++;
334
335 /* pick the first supported format */
336 for (i = 0; i < n; i++) {
337 if (screen->is_format_supported(screen, fmt[i],
338 PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) {
339 formats[count++] = fmt[i];
340 break;
341 }
342 }
343
344 fmt += n;
345 }
346
347 return count;
348 }
349
350 /**
351 * Add configs to display and return the next config ID.
352 */
353 static EGLint
354 egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
355 {
356 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
357 const struct native_config **native_configs;
358 enum pipe_format depth_stencil_formats[8];
359 int num_formats, num_configs, i, j;
360 int preserve_buffer, max_swap_interval;
361
362 native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
363 if (!num_configs) {
364 if (native_configs)
365 FREE(native_configs);
366 return id;
367 }
368
369 preserve_buffer =
370 gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER);
371 max_swap_interval =
372 gdpy->native->get_param(gdpy->native, NATIVE_PARAM_MAX_SWAP_INTERVAL);
373
374 num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
375 depth_stencil_formats);
376
377 for (i = 0; i < num_configs; i++) {
378 for (j = 0; j < num_formats; j++) {
379 struct egl_g3d_config *gconf;
380
381 gconf = CALLOC_STRUCT(egl_g3d_config);
382 if (gconf) {
383 _eglInitConfig(&gconf->base, dpy, id);
384 if (!egl_g3d_init_config(drv, dpy, &gconf->base,
385 native_configs[i], depth_stencil_formats[j],
386 preserve_buffer, max_swap_interval)) {
387 FREE(gconf);
388 break;
389 }
390
391 _eglLinkConfig(&gconf->base);
392 id++;
393 }
394 }
395 }
396
397 FREE(native_configs);
398 return id;
399 }
400
401 static void
402 egl_g3d_invalid_surface(struct native_display *ndpy,
403 struct native_surface *nsurf,
404 unsigned int seq_num)
405 {
406 /* XXX not thread safe? */
407 struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
408 struct egl_g3d_context *gctx;
409
410 /*
411 * Some functions such as egl_g3d_copy_buffers create a temporary native
412 * surface. There is no gsurf associated with it.
413 */
414 gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
415 if (gctx)
416 gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
417 }
418
419 static struct pipe_screen *
420 egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
421 {
422 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
423 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
424 return gdpy->loader->create_drm_screen(name, fd);
425 }
426
427 static struct pipe_screen *
428 egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
429 {
430 _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
431 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
432 return gdpy->loader->create_sw_screen(ws);
433 }
434
435 static struct native_event_handler egl_g3d_native_event_handler = {
436 egl_g3d_invalid_surface,
437 egl_g3d_new_drm_screen,
438 egl_g3d_new_sw_screen
439 };
440
441 static void
442 egl_g3d_free_config(void *conf)
443 {
444 struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf);
445 FREE(gconf);
446 }
447
448 static void
449 egl_g3d_free_screen(void *scr)
450 {
451 #ifdef EGL_MESA_screen_surface
452 struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr);
453 FREE(gscr->native_modes);
454 FREE(gscr);
455 #endif
456 }
457
458 static EGLBoolean
459 egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
460 {
461 struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
462
463 _eglReleaseDisplayResources(drv, dpy);
464
465 if (gdpy->pipe)
466 gdpy->pipe->destroy(gdpy->pipe);
467
468 if (dpy->Configs) {
469 _eglDestroyArray(dpy->Configs, egl_g3d_free_config);
470 dpy->Configs = NULL;
471 }
472 if (dpy->Screens) {
473 _eglDestroyArray(dpy->Screens, egl_g3d_free_screen);
474 dpy->Screens = NULL;
475 }
476
477 _eglCleanupDisplay(dpy);
478
479 if (gdpy->smapi)
480 egl_g3d_destroy_st_manager(gdpy->smapi);
481
482 if (gdpy->native)
483 gdpy->native->destroy(gdpy->native);
484
485 FREE(gdpy);
486 dpy->DriverData = NULL;
487
488 return EGL_TRUE;
489 }
490
491 static EGLBoolean
492 egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
493 EGLint *major, EGLint *minor)
494 {
495 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
496 struct egl_g3d_display *gdpy;
497 const struct native_platform *nplat;
498
499 nplat = egl_g3d_get_platform(drv, dpy->Platform);
500 if (!nplat)
501 return EGL_FALSE;
502
503 gdpy = CALLOC_STRUCT(egl_g3d_display);
504 if (!gdpy) {
505 _eglError(EGL_BAD_ALLOC, "eglInitialize");
506 goto fail;
507 }
508 gdpy->loader = gdrv->loader;
509 dpy->DriverData = gdpy;
510
511 _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay);
512 gdpy->native = nplat->create_display(dpy->PlatformDisplay,
513 &egl_g3d_native_event_handler, (void *) dpy);
514 if (!gdpy->native) {
515 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
516 goto fail;
517 }
518
519 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK)
520 dpy->ClientAPIsMask |= EGL_OPENGL_BIT;
521 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES1_MASK)
522 dpy->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
523 if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_OPENGL_ES2_MASK)
524 dpy->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
525 if (gdpy->loader->profile_masks[ST_API_OPENVG] & ST_PROFILE_DEFAULT_MASK)
526 dpy->ClientAPIsMask |= EGL_OPENVG_BIT;
527
528 gdpy->smapi = egl_g3d_create_st_manager(dpy);
529 if (!gdpy->smapi) {
530 _eglError(EGL_NOT_INITIALIZED,
531 "eglInitialize(failed to create st manager)");
532 goto fail;
533 }
534
535 #ifdef EGL_MESA_screen_surface
536 /* enable MESA_screen_surface before adding (and validating) configs */
537 if (gdpy->native->modeset) {
538 dpy->Extensions.MESA_screen_surface = EGL_TRUE;
539 egl_g3d_add_screens(drv, dpy);
540 }
541 #endif
542
543 dpy->Extensions.KHR_image_base = EGL_TRUE;
544 if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
545 dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
546
547 dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
548 dpy->Extensions.KHR_fence_sync = EGL_TRUE;
549
550 dpy->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
551 dpy->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
552 dpy->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
553
554 if (dpy->Platform == _EGL_PLATFORM_DRM) {
555 dpy->Extensions.MESA_drm_display = EGL_TRUE;
556 if (gdpy->native->buffer)
557 dpy->Extensions.MESA_drm_image = EGL_TRUE;
558 }
559
560 if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
561 _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
562 goto fail;
563 }
564
565 *major = 1;
566 *minor = 4;
567
568 return EGL_TRUE;
569
570 fail:
571 if (gdpy)
572 egl_g3d_terminate(drv, dpy);
573 return EGL_FALSE;
574 }
575
576 static _EGLProc
577 egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
578 {
579 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
580 struct st_api *stapi = NULL;
581
582 if (procname && procname[0] == 'v' && procname[1] == 'g')
583 stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
584 else if (procname && procname[0] == 'g' && procname[1] == 'l')
585 stapi = gdrv->loader->get_st_api(ST_API_OPENGL);
586
587 return (_EGLProc) ((stapi) ?
588 stapi->get_proc_address(stapi, procname) : NULL);
589 }
590
591 static EGLint
592 egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
593 {
594 return (egl_g3d_get_platform(drv, dpy->Platform)) ? 90 : 0;
595 }
596
597 _EGLDriver *
598 egl_g3d_create_driver(const struct egl_g3d_loader *loader)
599 {
600 struct egl_g3d_driver *gdrv;
601
602 gdrv = CALLOC_STRUCT(egl_g3d_driver);
603 if (!gdrv)
604 return NULL;
605
606 gdrv->loader = loader;
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.Probe = egl_g3d_probe;
614
615 /* to be filled by the caller */
616 gdrv->base.Name = NULL;
617 gdrv->base.Unload = NULL;
618
619 return &gdrv->base;
620 }
621
622 void
623 egl_g3d_destroy_driver(_EGLDriver *drv)
624 {
625 struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
626 FREE(gdrv);
627 }