Home | History | Annotate | Download | only in haiku
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 2014 Adrin Arroyo Calle <adrian.arroyocalle (at) 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_driver
     58 {
     59 	_EGLDriver base;
     60 };
     61 
     62 struct haiku_egl_config
     63 {
     64 	_EGLConfig         base;
     65 };
     66 
     67 struct haiku_egl_context
     68 {
     69 	_EGLContext	ctx;
     70 };
     71 
     72 struct haiku_egl_surface
     73 {
     74 	_EGLSurface surf;
     75 	BGLView* gl;
     76 };
     77 
     78 
     79 /**
     80  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
     81  */
     82 static _EGLSurface *
     83 haiku_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
     84 	_EGLConfig *conf, void *native_window, const EGLint *attrib_list)
     85 {
     86 	CALLED();
     87 
     88 	struct haiku_egl_surface* surface;
     89 	surface = (struct haiku_egl_surface*) calloc(1, sizeof (*surface));
     90 	if (!surface) {
     91 		_eglError(EGL_BAD_ALLOC, "haiku_create_window_surface");
     92 		return NULL;
     93 	}
     94 
     95 	if (!_eglInitSurface(&surface->surf, disp, EGL_WINDOW_BIT,
     96 		conf, attrib_list)) {
     97 		free(surface);
     98 		return NULL;
     99 	}
    100 
    101 	(&surface->surf)->SwapInterval = 1;
    102 
    103 	TRACE("Creating window\n");
    104 	BWindow* win = (BWindow*)native_window;
    105 
    106 	TRACE("Creating GL view\n");
    107 	surface->gl = new BGLView(win->Bounds(), "OpenGL", B_FOLLOW_ALL_SIDES, 0,
    108 		BGL_RGB | BGL_DOUBLE | BGL_ALPHA);
    109 
    110 	TRACE("Adding GL\n");
    111 	win->AddChild(surface->gl);
    112 
    113 	TRACE("Showing window\n");
    114 	win->Show();
    115 	return &surface->surf;
    116 }
    117 
    118 
    119 static _EGLSurface *
    120 haiku_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
    121 	_EGLConfig *conf, void *native_pixmap, const EGLint *attrib_list)
    122 {
    123 	return NULL;
    124 }
    125 
    126 
    127 static _EGLSurface *
    128 haiku_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
    129 	_EGLConfig *conf, const EGLint *attrib_list)
    130 {
    131 	return NULL;
    132 }
    133 
    134 
    135 static EGLBoolean
    136 haiku_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
    137 {
    138 	if (_eglPutSurface(surf)) {
    139 		// XXX: detach haiku_egl_surface::gl from the native window and destroy it
    140 		free(surf);
    141 	}
    142 	return EGL_TRUE;
    143 }
    144 
    145 
    146 static EGLBoolean
    147 haiku_add_configs_for_visuals(_EGLDisplay *dpy)
    148 {
    149 	CALLED();
    150 
    151 	struct haiku_egl_config* conf;
    152 	conf = (struct haiku_egl_config*) calloc(1, sizeof (*conf));
    153 	if (!conf) {
    154 		_eglError(EGL_BAD_ALLOC, "haiku_add_configs_for_visuals");
    155 		return EGL_FALSE;
    156 	}
    157 
    158 	_eglInitConfig(&conf->base, dpy, 1);
    159 	TRACE("Config inited\n");
    160 
    161 	_eglSetConfigKey(&conf->base, EGL_RED_SIZE, 8);
    162 	_eglSetConfigKey(&conf->base, EGL_BLUE_SIZE, 8);
    163 	_eglSetConfigKey(&conf->base, EGL_GREEN_SIZE, 8);
    164 	_eglSetConfigKey(&conf->base, EGL_LUMINANCE_SIZE, 0);
    165 	_eglSetConfigKey(&conf->base, EGL_ALPHA_SIZE, 8);
    166 	_eglSetConfigKey(&conf->base, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
    167 	EGLint r = (_eglGetConfigKey(&conf->base, EGL_RED_SIZE)
    168 		+ _eglGetConfigKey(&conf->base, EGL_GREEN_SIZE)
    169 		+ _eglGetConfigKey(&conf->base, EGL_BLUE_SIZE)
    170 		+ _eglGetConfigKey(&conf->base, EGL_ALPHA_SIZE));
    171 	_eglSetConfigKey(&conf->base, EGL_BUFFER_SIZE, r);
    172 	_eglSetConfigKey(&conf->base, EGL_CONFIG_CAVEAT, EGL_NONE);
    173 	_eglSetConfigKey(&conf->base, EGL_CONFIG_ID, 1);
    174 	_eglSetConfigKey(&conf->base, EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE);
    175 	_eglSetConfigKey(&conf->base, EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE);
    176 	_eglSetConfigKey(&conf->base, EGL_STENCIL_SIZE, 0);
    177 	_eglSetConfigKey(&conf->base, EGL_TRANSPARENT_TYPE, EGL_NONE);
    178 	_eglSetConfigKey(&conf->base, EGL_NATIVE_RENDERABLE, EGL_TRUE); // Let's say yes
    179 	_eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_ID, 0); // No visual
    180 	_eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_TYPE, EGL_NONE); // No visual
    181 	_eglSetConfigKey(&conf->base, EGL_RENDERABLE_TYPE, 0x8);
    182 	_eglSetConfigKey(&conf->base, EGL_SAMPLE_BUFFERS, 0); // TODO: How to get the right value ?
    183 	_eglSetConfigKey(&conf->base, EGL_SAMPLES, _eglGetConfigKey(&conf->base, EGL_SAMPLE_BUFFERS) == 0 ? 0 : 0);
    184 	_eglSetConfigKey(&conf->base, EGL_DEPTH_SIZE, 24); // TODO: How to get the right value ?
    185 	_eglSetConfigKey(&conf->base, EGL_LEVEL, 0);
    186 	_eglSetConfigKey(&conf->base, EGL_MAX_PBUFFER_WIDTH, 0); // TODO: How to get the right value ?
    187 	_eglSetConfigKey(&conf->base, EGL_MAX_PBUFFER_HEIGHT, 0); // TODO: How to get the right value ?
    188 	_eglSetConfigKey(&conf->base, EGL_MAX_PBUFFER_PIXELS, 0); // TODO: How to get the right value ?
    189 	_eglSetConfigKey(&conf->base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT /*| EGL_PIXMAP_BIT | EGL_PBUFFER_BIT*/);
    190 
    191 	TRACE("Config configuated\n");
    192 	if (!_eglValidateConfig(&conf->base, EGL_FALSE)) {
    193 		_eglLog(_EGL_DEBUG, "Haiku: failed to validate config");
    194 		goto cleanup;
    195 	}
    196 	TRACE("Validated config\n");
    197 
    198 	_eglLinkConfig(&conf->base);
    199 	if (!_eglGetArraySize(dpy->Configs)) {
    200 		_eglLog(_EGL_WARNING, "Haiku: failed to create any config");
    201 		goto cleanup;
    202 	}
    203 	TRACE("Config successfull\n");
    204 
    205 	return EGL_TRUE;
    206 
    207 cleanup:
    208 	free(conf);
    209 	return EGL_FALSE;
    210 }
    211 
    212 
    213 extern "C"
    214 EGLBoolean
    215 init_haiku(_EGLDriver *drv, _EGLDisplay *dpy)
    216 {
    217 	CALLED();
    218 
    219 	TRACE("Add configs\n");
    220 	if (!haiku_add_configs_for_visuals(dpy))
    221 		return EGL_FALSE;
    222 
    223 	dpy->Version = 14;
    224 
    225 	TRACE("Initialization finished\n");
    226 
    227 	return EGL_TRUE;
    228 }
    229 
    230 
    231 extern "C"
    232 EGLBoolean
    233 haiku_terminate(_EGLDriver* drv,_EGLDisplay* dpy)
    234 {
    235 	return EGL_TRUE;
    236 }
    237 
    238 
    239 extern "C"
    240 _EGLContext*
    241 haiku_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
    242 	_EGLContext *share_list, const EGLint *attrib_list)
    243 {
    244 	CALLED();
    245 
    246 	struct haiku_egl_context* context;
    247 	context = (struct haiku_egl_context*) calloc(1, sizeof (*context));
    248 	if (!context) {
    249 		_eglError(EGL_BAD_ALLOC, "haiku_create_context");
    250 		return NULL;
    251 	}
    252 
    253 	if (!_eglInitContext(&context->ctx, disp, conf, attrib_list))
    254 		goto cleanup;
    255 
    256 	TRACE("Context created\n");
    257 	return &context->ctx;
    258 
    259 cleanup:
    260 	free(context);
    261 	return NULL;
    262 }
    263 
    264 
    265 extern "C"
    266 EGLBoolean
    267 haiku_destroy_context(_EGLDriver* drv, _EGLDisplay *disp, _EGLContext* ctx)
    268 {
    269 	struct haiku_egl_context* context = haiku_egl_context(ctx);
    270 
    271 	if (_eglPutContext(ctx)) {
    272 		// XXX: teardown the context ?
    273 		free(context);
    274 		ctx = NULL;
    275 	}
    276 	return EGL_TRUE;
    277 }
    278 
    279 
    280 extern "C"
    281 EGLBoolean
    282 haiku_make_current(_EGLDriver* drv, _EGLDisplay* dpy, _EGLSurface *dsurf,
    283 	_EGLSurface *rsurf, _EGLContext *ctx)
    284 {
    285 	CALLED();
    286 
    287 	struct haiku_egl_context* cont = haiku_egl_context(ctx);
    288 	struct haiku_egl_surface* surf = haiku_egl_surface(dsurf);
    289 	_EGLContext *old_ctx;
    290 	_EGLSurface *old_dsurf, *old_rsurf;
    291 
    292 	if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
    293 		return EGL_FALSE;
    294 
    295 	//cont->ctx.DrawSurface=&surf->surf;
    296 	surf->gl->LockGL();
    297 	return EGL_TRUE;
    298 }
    299 
    300 
    301 extern "C"
    302 EGLBoolean
    303 haiku_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
    304 {
    305 	struct haiku_egl_surface* surface = haiku_egl_surface(surf);
    306 
    307 	surface->gl->SwapBuffers();
    308 	//gl->Render();
    309 	return EGL_TRUE;
    310 }
    311 
    312 
    313 extern "C"
    314 void
    315 haiku_unload(_EGLDriver* drv)
    316 {
    317 
    318 }
    319 
    320 
    321 /**
    322  * This is the main entrypoint into the driver, called by libEGL.
    323  * Create a new _EGLDriver object and init its dispatch table.
    324  */
    325 extern "C"
    326 _EGLDriver*
    327 _eglBuiltInDriverHaiku(const char *args)
    328 {
    329 	CALLED();
    330 
    331 	struct haiku_egl_driver* driver;
    332 	driver = (struct haiku_egl_driver*) calloc(1, sizeof(*driver));
    333 	if (!driver) {
    334 		_eglError(EGL_BAD_ALLOC, "_eglBuiltInDriverHaiku");
    335 		return NULL;
    336 	}
    337 
    338 	_eglInitDriverFallbacks(&driver->base);
    339 	driver->base.API.Initialize = init_haiku;
    340 	driver->base.API.Terminate = haiku_terminate;
    341 	driver->base.API.CreateContext = haiku_create_context;
    342 	driver->base.API.DestroyContext = haiku_destroy_context;
    343 	driver->base.API.MakeCurrent = haiku_make_current;
    344 	driver->base.API.CreateWindowSurface = haiku_create_window_surface;
    345 	driver->base.API.CreatePixmapSurface = haiku_create_pixmap_surface;
    346 	driver->base.API.CreatePbufferSurface = haiku_create_pbuffer_surface;
    347 	driver->base.API.DestroySurface = haiku_destroy_surface;
    348 
    349 	driver->base.API.SwapBuffers = haiku_swap_buffers;
    350 
    351 	driver->base.Name = "Haiku";
    352 	driver->base.Unload = haiku_unload;
    353 
    354 	TRACE("API Calls defined\n");
    355 
    356 	return &driver->base;
    357 }
    358