1 // Copyright 2012 Intel Corporation
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // - Redistributions of source code must retain the above copyright notice, this
9 //   list of conditions and the following disclaimer.
10 //
11 // - Redistributions in binary form must reproduce the above copyright notice,
12 //   this list of conditions and the following disclaimer in the documentation
13 //   and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #include <assert.h>
27 
28 #include "wcore_error.h"
29 #include "wcore_platform.h"
30 
31 #include "wegl_display.h"
32 #include "wegl_imports.h"
33 #include "wegl_util.h"
34 #include "wegl_platform.h"
35 
36 static bool
get_apis(struct wegl_display * dpy)37 get_apis(struct wegl_display *dpy)
38 {
39     struct wegl_platform *plat = wegl_platform(dpy->wcore.platform);
40     const char *apis = plat->eglQueryString(dpy->egl, EGL_CLIENT_APIS);
41 
42     // Our minimum requirement - EGL 1.2 ...
43     if (dpy->major_version != 1 || dpy->minor_version < 2) {
44         wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
45                      "EGL 1.2 or later is required");
46         return false;
47     }
48 
49     // ... plus working eglQueryString(EGL_CLIENT_APIS).
50     if (!apis) {
51         wegl_emit_error(plat, "eglQueryString(EGL_CLIENT_APIS)");
52         return false;
53     }
54 
55     // waffle_is_extension_in_string() resets the error state. That's ok,
56     // however, because if we've reached this point then no error should be
57     // pending emission.
58     assert(wcore_error_get_code() == 0);
59 
60     if (waffle_is_extension_in_string(apis, "OpenGL_ES"))
61         dpy->api_mask |= WEGL_OPENGL_ES_API;
62 
63     // Check for "OpenGL" if we're running EGL 1.4 or later.
64     if (dpy->major_version == 1 && dpy->minor_version >= 4)
65         if (waffle_is_extension_in_string(apis, "OpenGL"))
66             dpy->api_mask |= WEGL_OPENGL_API;
67 
68     return true;
69 }
70 
71 static bool
get_extensions(struct wegl_display * dpy)72 get_extensions(struct wegl_display *dpy)
73 {
74     struct wegl_platform *plat = wegl_platform(dpy->wcore.platform);
75     const char *extensions = plat->eglQueryString(dpy->egl, EGL_EXTENSIONS);
76 
77     if (!extensions) {
78         wegl_emit_error(plat, "eglQueryString(EGL_EXTENSIONS)");
79         return false;
80     }
81 
82     // waffle_is_extension_in_string() resets the error state. That's ok,
83     // however, because if we've reached this point then no error should be
84     // pending emission.
85     assert(wcore_error_get_code() == 0);
86 
87 #define CHECK_EXTENSION(ext) \
88     dpy->ext = waffle_is_extension_in_string(extensions, "EGL_" #ext)
89 
90     CHECK_EXTENSION(EXT_create_context_robustness);
91     CHECK_EXTENSION(KHR_create_context);
92     CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers);
93 
94 #undef CHECK_EXTENSION
95 
96     return true;
97 }
98 
99 /// On Linux, according to eglplatform.h, EGLNativeDisplayType and intptr_t
100 /// have the same size regardless of platform.
101 bool
wegl_display_init(struct wegl_display * dpy,struct wcore_platform * wc_plat,void * native_display)102 wegl_display_init(struct wegl_display *dpy,
103                   struct wcore_platform *wc_plat,
104                   void *native_display)
105 {
106     struct wegl_platform *plat = wegl_platform(wc_plat);
107     bool ok;
108 
109     ok = wcore_display_init(&dpy->wcore, wc_plat);
110     if (!ok)
111         goto fail;
112 
113     if (wegl_platform_can_use_eglGetPlatformDisplay(plat)) {
114         dpy->egl = plat->eglGetPlatformDisplay(plat->egl_platform,
115                                                native_display, NULL);
116         if (!dpy->egl) {
117             wegl_emit_error(plat, "eglGetPlatformDisplay");
118             goto fail;
119         }
120     } else if (wegl_platform_can_use_eglGetPlatformDisplayEXT(plat)) {
121         dpy->egl = plat->eglGetPlatformDisplayEXT(plat->egl_platform,
122                                                   native_display, NULL);
123         if (!dpy->egl) {
124             wegl_emit_error(plat, "eglGetPlatformDisplayEXT");
125             goto fail;
126         }
127     } else {
128         dpy->egl = plat->eglGetDisplay((EGLNativeDisplayType) native_display);
129         if (!dpy->egl) {
130             wegl_emit_error(plat, "eglGetDisplay");
131             goto fail;
132         }
133     }
134 
135     ok = plat->eglInitialize(dpy->egl, &dpy->major_version, &dpy->minor_version);
136     if (!ok) {
137         wegl_emit_error(plat, "eglInitialize");
138         goto fail;
139     }
140 
141     ok = get_apis(dpy);
142     if (!ok)
143         goto fail;
144 
145     ok = get_extensions(dpy);
146     if (!ok)
147         goto fail;
148 
149     return true;
150 
151 fail:
152     wegl_display_teardown(dpy);
153     return false;
154 }
155 
156 bool
wegl_display_teardown(struct wegl_display * dpy)157 wegl_display_teardown(struct wegl_display *dpy)
158 {
159     struct wegl_platform *plat = wegl_platform(dpy->wcore.platform);
160     bool ok = true;
161 
162     if (dpy->egl) {
163         ok = plat->eglTerminate(dpy->egl);
164         if (!ok)
165             wegl_emit_error(plat, "eglTerminate");
166     }
167 
168     return ok;
169 }
170 
171 bool
wegl_display_supports_context_api(struct wcore_display * wc_dpy,int32_t waffle_context_api)172 wegl_display_supports_context_api(struct wcore_display *wc_dpy,
173                                   int32_t waffle_context_api)
174 {
175     struct wegl_display *dpy = wegl_display(wc_dpy);
176 
177     switch (waffle_context_api) {
178         case WAFFLE_CONTEXT_OPENGL:
179             return !!(dpy->api_mask & WEGL_OPENGL_API);
180         case WAFFLE_CONTEXT_OPENGL_ES1:
181         case WAFFLE_CONTEXT_OPENGL_ES2:
182             return !!(dpy->api_mask & WEGL_OPENGL_ES_API);
183         case WAFFLE_CONTEXT_OPENGL_ES3:
184             return !!(dpy->api_mask & WEGL_OPENGL_ES_API) &&
185                    dpy->KHR_create_context;
186         default:
187             assert(false);
188             return false;
189     }
190 }
191