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