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