• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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