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->CreateWindowSurface(). 77 */ 78static _EGLSurface * 79haiku_create_window_surface(_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, native_window)) { 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(_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(_EGLDisplay *disp, 125 _EGLConfig *conf, const EGLint *attrib_list) 126{ 127 return NULL; 128} 129 130 131static EGLBoolean 132haiku_destroy_surface(_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 conf->base.RedSize = 8; 156 conf->base.BlueSize = 8; 157 conf->base.GreenSize = 8; 158 conf->base.LuminanceSize = 0; 159 conf->base.AlphaSize = 8; 160 conf->base.ColorBufferType = EGL_RGB_BUFFER; 161 conf->base.BufferSize = conf->base.RedSize 162 + conf->base.GreenSize 163 + conf->base.BlueSize 164 + conf->base.AlphaSize; 165 conf->base.ConfigCaveat = EGL_NONE; 166 conf->base.ConfigID = 1; 167 conf->base.BindToTextureRGB = EGL_FALSE; 168 conf->base.BindToTextureRGBA = EGL_FALSE; 169 conf->base.StencilSize = 0; 170 conf->base.TransparentType = EGL_NONE; 171 conf->base.NativeRenderable = EGL_TRUE; // Let's say yes 172 conf->base.NativeVisualID = 0; // No visual 173 conf->base.NativeVisualType = EGL_NONE; // No visual 174 conf->base.RenderableType = 0x8; 175 conf->base.SampleBuffers = 0; // TODO: How to get the right value ? 176 conf->base.Samples = conf->base.SampleBuffers == 0 ? 0 : 0; 177 conf->base.DepthSize = 24; // TODO: How to get the right value ? 178 conf->base.Level = 0; 179 conf->base.MaxPbufferWidth = 0; // TODO: How to get the right value ? 180 conf->base.MaxPbufferHeight = 0; // TODO: How to get the right value ? 181 conf->base.MaxPbufferPixels = 0; // TODO: How to get the right value ? 182 conf->base.SurfaceType = 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(disp->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 200cleanup: 201 free(conf); 202 return EGL_FALSE; 203} 204 205 206extern "C" 207EGLBoolean 208init_haiku(_EGLDisplay *disp) 209{ 210 _EGLDevice *dev; 211 CALLED(); 212 213 dev = _eglAddDevice(-1, true); 214 if (!dev) { 215 _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice"); 216 return EGL_FALSE; 217 } 218 disp->Device = dev; 219 220 TRACE("Add configs\n"); 221 if (!haiku_add_configs_for_visuals(disp)) 222 return EGL_FALSE; 223 224 TRACE("Initialization finished\n"); 225 226 return EGL_TRUE; 227} 228 229 230extern "C" 231EGLBoolean 232haiku_terminate(_EGLDisplay *disp) 233{ 234 return EGL_TRUE; 235} 236 237 238extern "C" 239_EGLContext* 240haiku_create_context(_EGLDisplay *disp, _EGLConfig *conf, 241 _EGLContext *share_list, const EGLint *attrib_list) 242{ 243 CALLED(); 244 245 struct haiku_egl_context* context; 246 context = (struct haiku_egl_context*) calloc(1, sizeof (*context)); 247 if (!context) { 248 _eglError(EGL_BAD_ALLOC, "haiku_create_context"); 249 return NULL; 250 } 251 252 if (!_eglInitContext(&context->ctx, disp, conf, attrib_list)) 253 goto cleanup; 254 255 TRACE("Context created\n"); 256 return &context->ctx; 257 258cleanup: 259 free(context); 260 return NULL; 261} 262 263 264extern "C" 265EGLBoolean 266haiku_destroy_context(_EGLDisplay *disp, _EGLContext* ctx) 267{ 268 struct haiku_egl_context* context = haiku_egl_context(ctx); 269 270 if (_eglPutContext(ctx)) { 271 // XXX: teardown the context ? 272 free(context); 273 ctx = NULL; 274 } 275 return EGL_TRUE; 276} 277 278 279extern "C" 280EGLBoolean 281haiku_make_current(_EGLDisplay *disp, _EGLSurface *dsurf, 282 _EGLSurface *rsurf, _EGLContext *ctx) 283{ 284 CALLED(); 285 286 struct haiku_egl_context* cont = haiku_egl_context(ctx); 287 struct haiku_egl_surface* surf = haiku_egl_surface(dsurf); 288 _EGLContext *old_ctx; 289 _EGLSurface *old_dsurf, *old_rsurf; 290 291 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 292 return EGL_FALSE; 293 294 //cont->ctx.DrawSurface=&surf->surf; 295 surf->gl->LockGL(); 296 return EGL_TRUE; 297} 298 299 300extern "C" 301EGLBoolean 302haiku_swap_buffers(_EGLDisplay *disp, _EGLSurface *surf) 303{ 304 struct haiku_egl_surface* surface = haiku_egl_surface(surf); 305 306 surface->gl->SwapBuffers(); 307 //gl->Render(); 308 return EGL_TRUE; 309} 310 311 312extern "C" 313const _EGLDriver _eglDriver = { 314 .Initialize = init_haiku, 315 .Terminate = haiku_terminate, 316 .CreateContext = haiku_create_context, 317 .DestroyContext = haiku_destroy_context, 318 .MakeCurrent = haiku_make_current, 319 .CreateWindowSurface = haiku_create_window_surface, 320 .CreatePixmapSurface = haiku_create_pixmap_surface, 321 .CreatePbufferSurface = haiku_create_pbuffer_surface, 322 .DestroySurface = haiku_destroy_surface, 323 .SwapBuffers = haiku_swap_buffers, 324}; 325