1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2014 Adrián Arroyo Calle <adrian.arroyocalle@gmail.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <errno.h>
26 #include <dlfcn.h>
27 #include <stdint.h>
28 #include <stdio.h>
29
30 #include "eglconfig.h"
31 #include "eglcontext.h"
32 #include "egldisplay.h"
33 #include "egldriver.h"
34 #include "eglcurrent.h"
35 #include "egllog.h"
36 #include "eglsurface.h"
37 #include "eglimage.h"
38 #include "egltypedefs.h"
39
40 #include <InterfaceKit.h>
41 #include <OpenGLKit.h>
42
43
44 #ifdef DEBUG
45 # define TRACE(x...) printf("egl_haiku: " x)
46 # define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
47 #else
48 # define TRACE(x...)
49 # define CALLED()
50 #endif
51 #define ERROR(x...) printf("egl_haiku: " x)
52
53
54 _EGL_DRIVER_STANDARD_TYPECASTS(haiku_egl)
55
56
57 struct haiku_egl_config
58 {
59 _EGLConfig base;
60 };
61
62 struct haiku_egl_context
63 {
64 _EGLContext ctx;
65 };
66
67 struct haiku_egl_surface
68 {
69 _EGLSurface surf;
70 BGLView* gl;
71 };
72
73
74 /**
75 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
76 */
77 static _EGLSurface *
haiku_create_window_surface(_EGLDriver * drv,_EGLDisplay * disp,_EGLConfig * conf,void * native_window,const EGLint * attrib_list)78 haiku_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
79 _EGLConfig *conf, void *native_window, const EGLint *attrib_list)
80 {
81 CALLED();
82
83 struct haiku_egl_surface* surface;
84 surface = (struct haiku_egl_surface*) calloc(1, sizeof (*surface));
85 if (!surface) {
86 _eglError(EGL_BAD_ALLOC, "haiku_create_window_surface");
87 return NULL;
88 }
89
90 if (!_eglInitSurface(&surface->surf, disp, EGL_WINDOW_BIT,
91 conf, attrib_list)) {
92 free(surface);
93 return NULL;
94 }
95
96 (&surface->surf)->SwapInterval = 1;
97
98 TRACE("Creating window\n");
99 BWindow* win = (BWindow*)native_window;
100
101 TRACE("Creating GL view\n");
102 surface->gl = new BGLView(win->Bounds(), "OpenGL", B_FOLLOW_ALL_SIDES, 0,
103 BGL_RGB | BGL_DOUBLE | BGL_ALPHA);
104
105 TRACE("Adding GL\n");
106 win->AddChild(surface->gl);
107
108 TRACE("Showing window\n");
109 win->Show();
110 return &surface->surf;
111 }
112
113
114 static _EGLSurface *
haiku_create_pixmap_surface(_EGLDriver * drv,_EGLDisplay * disp,_EGLConfig * conf,void * native_pixmap,const EGLint * attrib_list)115 haiku_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
116 _EGLConfig *conf, void *native_pixmap, const EGLint *attrib_list)
117 {
118 return NULL;
119 }
120
121
122 static _EGLSurface *
haiku_create_pbuffer_surface(_EGLDriver * drv,_EGLDisplay * disp,_EGLConfig * conf,const EGLint * attrib_list)123 haiku_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
124 _EGLConfig *conf, const EGLint *attrib_list)
125 {
126 return NULL;
127 }
128
129
130 static EGLBoolean
haiku_destroy_surface(_EGLDriver * drv,_EGLDisplay * disp,_EGLSurface * surf)131 haiku_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
132 {
133 if (_eglPutSurface(surf)) {
134 // XXX: detach haiku_egl_surface::gl from the native window and destroy it
135 free(surf);
136 }
137 return EGL_TRUE;
138 }
139
140
141 static EGLBoolean
haiku_add_configs_for_visuals(_EGLDisplay * dpy)142 haiku_add_configs_for_visuals(_EGLDisplay *dpy)
143 {
144 CALLED();
145
146 struct haiku_egl_config* conf;
147 conf = (struct haiku_egl_config*) calloc(1, sizeof (*conf));
148 if (!conf)
149 return _eglError(EGL_BAD_ALLOC, "haiku_add_configs_for_visuals");
150
151 _eglInitConfig(&conf->base, dpy, 1);
152 TRACE("Config inited\n");
153
154 _eglSetConfigKey(&conf->base, EGL_RED_SIZE, 8);
155 _eglSetConfigKey(&conf->base, EGL_BLUE_SIZE, 8);
156 _eglSetConfigKey(&conf->base, EGL_GREEN_SIZE, 8);
157 _eglSetConfigKey(&conf->base, EGL_LUMINANCE_SIZE, 0);
158 _eglSetConfigKey(&conf->base, EGL_ALPHA_SIZE, 8);
159 _eglSetConfigKey(&conf->base, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
160 EGLint r = (_eglGetConfigKey(&conf->base, EGL_RED_SIZE)
161 + _eglGetConfigKey(&conf->base, EGL_GREEN_SIZE)
162 + _eglGetConfigKey(&conf->base, EGL_BLUE_SIZE)
163 + _eglGetConfigKey(&conf->base, EGL_ALPHA_SIZE));
164 _eglSetConfigKey(&conf->base, EGL_BUFFER_SIZE, r);
165 _eglSetConfigKey(&conf->base, EGL_CONFIG_CAVEAT, EGL_NONE);
166 _eglSetConfigKey(&conf->base, EGL_CONFIG_ID, 1);
167 _eglSetConfigKey(&conf->base, EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE);
168 _eglSetConfigKey(&conf->base, EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE);
169 _eglSetConfigKey(&conf->base, EGL_STENCIL_SIZE, 0);
170 _eglSetConfigKey(&conf->base, EGL_TRANSPARENT_TYPE, EGL_NONE);
171 _eglSetConfigKey(&conf->base, EGL_NATIVE_RENDERABLE, EGL_TRUE); // Let's say yes
172 _eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_ID, 0); // No visual
173 _eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_TYPE, EGL_NONE); // No visual
174 _eglSetConfigKey(&conf->base, EGL_RENDERABLE_TYPE, 0x8);
175 _eglSetConfigKey(&conf->base, EGL_SAMPLE_BUFFERS, 0); // TODO: How to get the right value ?
176 _eglSetConfigKey(&conf->base, EGL_SAMPLES, _eglGetConfigKey(&conf->base, EGL_SAMPLE_BUFFERS) == 0 ? 0 : 0);
177 _eglSetConfigKey(&conf->base, EGL_DEPTH_SIZE, 24); // TODO: How to get the right value ?
178 _eglSetConfigKey(&conf->base, EGL_LEVEL, 0);
179 _eglSetConfigKey(&conf->base, EGL_MAX_PBUFFER_WIDTH, 0); // TODO: How to get the right value ?
180 _eglSetConfigKey(&conf->base, EGL_MAX_PBUFFER_HEIGHT, 0); // TODO: How to get the right value ?
181 _eglSetConfigKey(&conf->base, EGL_MAX_PBUFFER_PIXELS, 0); // TODO: How to get the right value ?
182 _eglSetConfigKey(&conf->base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT /*| EGL_PIXMAP_BIT | EGL_PBUFFER_BIT*/);
183
184 TRACE("Config configuated\n");
185 if (!_eglValidateConfig(&conf->base, EGL_FALSE)) {
186 _eglLog(_EGL_DEBUG, "Haiku: failed to validate config");
187 goto cleanup;
188 }
189 TRACE("Validated config\n");
190
191 _eglLinkConfig(&conf->base);
192 if (!_eglGetArraySize(dpy->Configs)) {
193 _eglLog(_EGL_WARNING, "Haiku: failed to create any config");
194 goto cleanup;
195 }
196 TRACE("Config successfull\n");
197
198 return EGL_TRUE;
199
200 cleanup:
201 free(conf);
202 return EGL_FALSE;
203 }
204
205
206 extern "C"
207 EGLBoolean
init_haiku(_EGLDriver * drv,_EGLDisplay * dpy)208 init_haiku(_EGLDriver *drv, _EGLDisplay *dpy)
209 {
210 CALLED();
211
212 TRACE("Add configs\n");
213 if (!haiku_add_configs_for_visuals(dpy))
214 return EGL_FALSE;
215
216 dpy->Version = 14;
217
218 TRACE("Initialization finished\n");
219
220 return EGL_TRUE;
221 }
222
223
224 extern "C"
225 EGLBoolean
haiku_terminate(_EGLDriver * drv,_EGLDisplay * dpy)226 haiku_terminate(_EGLDriver* drv,_EGLDisplay* dpy)
227 {
228 return EGL_TRUE;
229 }
230
231
232 extern "C"
233 _EGLContext*
haiku_create_context(_EGLDriver * drv,_EGLDisplay * disp,_EGLConfig * conf,_EGLContext * share_list,const EGLint * attrib_list)234 haiku_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
235 _EGLContext *share_list, const EGLint *attrib_list)
236 {
237 CALLED();
238
239 struct haiku_egl_context* context;
240 context = (struct haiku_egl_context*) calloc(1, sizeof (*context));
241 if (!context) {
242 _eglError(EGL_BAD_ALLOC, "haiku_create_context");
243 return NULL;
244 }
245
246 if (!_eglInitContext(&context->ctx, disp, conf, attrib_list))
247 goto cleanup;
248
249 TRACE("Context created\n");
250 return &context->ctx;
251
252 cleanup:
253 free(context);
254 return NULL;
255 }
256
257
258 extern "C"
259 EGLBoolean
haiku_destroy_context(_EGLDriver * drv,_EGLDisplay * disp,_EGLContext * ctx)260 haiku_destroy_context(_EGLDriver* drv, _EGLDisplay *disp, _EGLContext* ctx)
261 {
262 struct haiku_egl_context* context = haiku_egl_context(ctx);
263
264 if (_eglPutContext(ctx)) {
265 // XXX: teardown the context ?
266 free(context);
267 ctx = NULL;
268 }
269 return EGL_TRUE;
270 }
271
272
273 extern "C"
274 EGLBoolean
haiku_make_current(_EGLDriver * drv,_EGLDisplay * dpy,_EGLSurface * dsurf,_EGLSurface * rsurf,_EGLContext * ctx)275 haiku_make_current(_EGLDriver* drv, _EGLDisplay* dpy, _EGLSurface *dsurf,
276 _EGLSurface *rsurf, _EGLContext *ctx)
277 {
278 CALLED();
279
280 struct haiku_egl_context* cont = haiku_egl_context(ctx);
281 struct haiku_egl_surface* surf = haiku_egl_surface(dsurf);
282 _EGLContext *old_ctx;
283 _EGLSurface *old_dsurf, *old_rsurf;
284
285 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
286 return EGL_FALSE;
287
288 //cont->ctx.DrawSurface=&surf->surf;
289 surf->gl->LockGL();
290 return EGL_TRUE;
291 }
292
293
294 extern "C"
295 EGLBoolean
haiku_swap_buffers(_EGLDriver * drv,_EGLDisplay * dpy,_EGLSurface * surf)296 haiku_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
297 {
298 struct haiku_egl_surface* surface = haiku_egl_surface(surf);
299
300 surface->gl->SwapBuffers();
301 //gl->Render();
302 return EGL_TRUE;
303 }
304
305
306 /**
307 * This is the main entrypoint into the driver, called by libEGL.
308 * Create a new _EGLDriver object and init its dispatch table.
309 */
310 extern "C"
311 _EGLDriver*
_eglBuiltInDriver(void)312 _eglBuiltInDriver(void)
313 {
314 CALLED();
315
316 _EGLDriver* driver;
317 driver = (_EGLDriver*) calloc(1, sizeof(*driver));
318 if (!driver) {
319 _eglError(EGL_BAD_ALLOC, "_eglBuiltInDriverHaiku");
320 return NULL;
321 }
322
323 _eglInitDriverFallbacks(driver);
324 driver->API.Initialize = init_haiku;
325 driver->API.Terminate = haiku_terminate;
326 driver->API.CreateContext = haiku_create_context;
327 driver->API.DestroyContext = haiku_destroy_context;
328 driver->API.MakeCurrent = haiku_make_current;
329 driver->API.CreateWindowSurface = haiku_create_window_surface;
330 driver->API.CreatePixmapSurface = haiku_create_pixmap_surface;
331 driver->API.CreatePbufferSurface = haiku_create_pbuffer_surface;
332 driver->API.DestroySurface = haiku_destroy_surface;
333
334 driver->API.SwapBuffers = haiku_swap_buffers;
335
336 driver->Name = "Haiku";
337
338 TRACE("API Calls defined\n");
339
340 return driver;
341 }
342