at main 48 kB view raw
1#include "bite.h" 2 3#if defined(_WIN32) 4#include <windows.h> 5#ifndef WINDOWS_LEAN_AND_MEAN 6#define WINDOWS_LEAN_AND_MEAN 1 7#endif 8#include <gl/GL.h> 9#include <gl/GLU.h> 10#include <tchar.h> 11#elif defined(__EMSCRIPTEN__) 12#include <GLES2/gl2.h> 13#include <emscripten.h> 14#include <emscripten/html5.h> 15#include <time.h> 16#else 17#include <GL/gl.h> 18#include <GL/glx.h> 19#include <X11/Xlib.h> 20#include <X11/Xutil.h> 21#include <X11/XKBlib.h> 22#include <dlfcn.h> 23#include <time.h> 24#include <unistd.h> 25#endif 26 27#if defined(_WIN32) 28char keys[512] = { 29 [VK_BACK] = BITEK_BACKSPACE, 30 [VK_TAB] = BITEK_TAB, 31 [VK_RETURN] = BITEK_RETURN, 32 [VK_SHIFT] = BITEK_SHIFT, 33 [VK_CONTROL] = BITEK_CONTROL, 34 35 [VK_ESCAPE] = BITEK_ESCAPE, 36 [VK_SPACE] = BITEK_SPACE, 37 [VK_PRIOR] = BITEK_PAGEUP, 38 [VK_NEXT] = BITEK_PAGEDOWN, 39 40 [VK_LEFT] = BITEK_LEFT, 41 [VK_UP] = BITEK_UP, 42 [VK_RIGHT] = BITEK_RIGHT, 43 [VK_DOWN] = BITEK_DOWN, 44 45 [VK_END] = BITEK_END, 46 [VK_HOME] = BITEK_HOME, 47 [VK_INSERT] = BITEK_INSERT, 48 [VK_DELETE] = BITEK_DELETE, 49 50 [0x30] = BITEK_0, 51 [0x31] = BITEK_1, 52 [0x32] = BITEK_2, 53 [0x33] = BITEK_3, 54 [0x34] = BITEK_4, 55 [0x35] = BITEK_5, 56 [0x36] = BITEK_6, 57 [0x37] = BITEK_7, 58 [0x38] = BITEK_8, 59 [0x39] = BITEK_9, 60 61 [0x41] = BITEK_A, 62 [0x42] = BITEK_B, 63 [0x43] = BITEK_C, 64 [0x44] = BITEK_D, 65 [0x45] = BITEK_E, 66 [0x46] = BITEK_F, 67 [0x47] = BITEK_G, 68 [0x48] = BITEK_H, 69 [0x49] = BITEK_I, 70 [0x4A] = BITEK_J, 71 [0x4B] = BITEK_K, 72 [0x4C] = BITEK_L, 73 [0x4D] = BITEK_M, 74 [0x4E] = BITEK_N, 75 [0x4F] = BITEK_O, 76 [0x50] = BITEK_P, 77 [0x51] = BITEK_Q, 78 [0x52] = BITEK_R, 79 [0x53] = BITEK_S, 80 [0x54] = BITEK_T, 81 [0x55] = BITEK_U, 82 [0x56] = BITEK_V, 83 [0x57] = BITEK_W, 84 [0x58] = BITEK_X, 85 [0x59] = BITEK_Y, 86 [0x5A] = BITEK_Z, 87}; 88#else 89char keys[] = { 90 [XK_BackSpace] = BITEK_BACKSPACE, 91 [XK_Tab] = BITEK_TAB, 92 [XK_Return] = BITEK_RETURN, 93 [XK_Escape] = BITEK_ESCAPE, 94 [XK_Delete] = BITEK_DELETE, 95 [XK_space] = BITEK_SPACE, 96 [XK_Alt_L] = BITEK_LALT, 97 [XK_Alt_R] = BITEK_RALT, 98 [XK_Shift_L] = BITEK_LSHIFT, 99 [XK_Shift_R] = BITEK_RSHIFT, 100 [XK_Control_L] = BITEK_LCONTROL, 101 [XK_Control_R] = BITEK_RCONTROL, 102 [XK_Super_L] = BITEK_LSUPER, 103 [XK_Super_R] = BITEK_RSUPER, 104 105 [XK_Left] = BITEK_LEFT, 106 [XK_Up] = BITEK_UP, 107 [XK_Right] = BITEK_RIGHT, 108 [XK_Down] = BITEK_DOWN, 109 110 [XK_Page_Up] = BITEK_PAGEUP, 111 [XK_Page_Down] = BITEK_PAGEDOWN, 112 113 [XK_End] = BITEK_END, 114 [XK_Home] = BITEK_HOME, 115 116 [XK_0] = BITEK_0, 117 [XK_1] = BITEK_1, 118 [XK_2] = BITEK_2, 119 [XK_3] = BITEK_3, 120 [XK_4] = BITEK_4, 121 [XK_5] = BITEK_5, 122 [XK_6] = BITEK_6, 123 [XK_7] = BITEK_7, 124 [XK_8] = BITEK_8, 125 [XK_9] = BITEK_9, 126 127 [XK_A] = BITEK_A, 128 [XK_B] = BITEK_B, 129 [XK_C] = BITEK_C, 130 [XK_D] = BITEK_D, 131 [XK_E] = BITEK_E, 132 [XK_F] = BITEK_F, 133 [XK_G] = BITEK_G, 134 [XK_H] = BITEK_H, 135 [XK_I] = BITEK_I, 136 [XK_J] = BITEK_J, 137 [XK_K] = BITEK_K, 138 [XK_L] = BITEK_L, 139 [XK_M] = BITEK_M, 140 [XK_N] = BITEK_N, 141 [XK_O] = BITEK_O, 142 [XK_P] = BITEK_P, 143 [XK_Q] = BITEK_Q, 144 [XK_R] = BITEK_R, 145 [XK_S] = BITEK_S, 146 [XK_T] = BITEK_T, 147 [XK_U] = BITEK_U, 148 [XK_V] = BITEK_V, 149 [XK_W] = BITEK_W, 150 [XK_X] = BITEK_X, 151 [XK_Y] = BITEK_Y, 152 [XK_Z] = BITEK_Z, 153 154 [XK_a] = BITEK_A, 155 [XK_b] = BITEK_B, 156 [XK_c] = BITEK_C, 157 [XK_d] = BITEK_D, 158 [XK_e] = BITEK_E, 159 [XK_f] = BITEK_F, 160 [XK_g] = BITEK_G, 161 [XK_h] = BITEK_H, 162 [XK_i] = BITEK_I, 163 [XK_j] = BITEK_J, 164 [XK_k] = BITEK_K, 165 [XK_l] = BITEK_L, 166 [XK_m] = BITEK_M, 167 [XK_n] = BITEK_N, 168 [XK_o] = BITEK_O, 169 [XK_p] = BITEK_P, 170 [XK_q] = BITEK_Q, 171 [XK_r] = BITEK_R, 172 [XK_s] = BITEK_S, 173 [XK_t] = BITEK_T, 174 [XK_u] = BITEK_U, 175 [XK_v] = BITEK_V, 176 [XK_w] = BITEK_W, 177 [XK_x] = BITEK_X, 178 [XK_y] = BITEK_Y, 179 [XK_z] = BITEK_Z, 180 181 [XK_KP_0] = BITEK_NUMPAD0, 182 [XK_KP_1] = BITEK_NUMPAD1, 183 [XK_KP_2] = BITEK_NUMPAD2, 184 [XK_KP_3] = BITEK_NUMPAD3, 185 [XK_KP_4] = BITEK_NUMPAD4, 186 [XK_KP_5] = BITEK_NUMPAD5, 187 [XK_KP_6] = BITEK_NUMPAD6, 188 [XK_KP_7] = BITEK_NUMPAD7, 189 [XK_KP_8] = BITEK_NUMPAD8, 190 [XK_KP_9] = BITEK_NUMPAD9, 191 192 [XK_F1] = BITEK_F1, 193 [XK_F2] = BITEK_F2, 194 [XK_F3] = BITEK_F3, 195 [XK_F4] = BITEK_F4, 196 [XK_F5] = BITEK_F5, 197 [XK_F6] = BITEK_F6, 198 [XK_F7] = BITEK_F7, 199 [XK_F8] = BITEK_F8, 200 [XK_F9] = BITEK_F9, 201 [XK_F10] = BITEK_F10, 202 [XK_F11] = BITEK_F11, 203 [XK_F12] = BITEK_F12, 204 205 [XK_minus] = BITEK_MINUS, 206 [XK_plus] = BITEK_PLUS, 207 [XK_less] = BITEK_LESS, 208 [XK_equal] = BITEK_EQUAL, 209 [XK_greater] = BITEK_GREATER, 210}; 211#endif 212 213struct be_Shader { 214 GLuint handle; 215 GLint world_uniform, modelview_uniform; 216}; 217 218struct be_Texture { 219 GLuint handle; 220 int width, height; 221 int filter[2]; 222 int wrap[2]; 223}; 224 225struct be_Framebuffer { 226 GLuint handle; 227 be_Texture texture; 228}; 229 230struct be_Window { 231 int x, y; 232 int width, height; 233#if defined(_WIN32) 234 HWND handle; 235 HDC dev_context; 236#elif defined(__EMSCRIPTEN__) 237#else 238 Display *display; 239 Window handle; 240 Colormap map; 241 242 GLXFBConfig fbconf; 243#endif 244}; 245 246typedef struct be_Render be_Render; 247struct be_Render { 248#if defined(_WIN32) 249 HGLRC gl_context; 250#elif defined(__EMSCRIPTEN__) 251 EMSCRIPTEN_WEBGL_CONTEXT_HANDLE gl_context; 252#else 253 GLXContext gl_context; 254#endif 255 256 int mode; 257 GLuint vao, vbo; 258}; 259 260struct be_Context { 261 int running; 262 be_Window window; 263 be_Render render; 264 be_EventCallback callbacks[BITE_EVENTS]; 265}; 266 267static be_Context _context; 268 269static const be_Config _conf = {.window = {.title = "bitEngine " BITE_VERSION, 270 .width = 640, 271 .height = 380, 272 .flags = 0}}; 273 274#if defined(_WIN32) 275typedef HGLRC WINAPI wglCreateContextAttribsARBProc(HDC hdc, 276 HGLRC hShareContext, 277 const int *attribList); 278wglCreateContextAttribsARBProc *wglCreateContextAttribsARB; 279#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 280#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 281#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 282#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 283#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 284 285typedef BOOL WINAPI wglChoosePixelFormatARBProc( 286 HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, 287 UINT nMaxFormats, int *piFormats, UINT *nNumFormats); 288wglChoosePixelFormatARBProc *wglChoosePixelFormatARB; 289 290// See 291// https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_pixel_format.txt 292// for all values 293#define WGL_DRAW_TO_WINDOW_ARB 0x2001 294#define WGL_ACCELERATION_ARB 0x2003 295#define WGL_SUPPORT_OPENGL_ARB 0x2010 296#define WGL_DOUBLE_BUFFER_ARB 0x2011 297#define WGL_PIXEL_TYPE_ARB 0x2013 298#define WGL_COLOR_BITS_ARB 0x2014 299#define WGL_DEPTH_BITS_ARB 0x2022 300#define WGL_STENCIL_BITS_ARB 0x2023 301 302#define WGL_FULL_ACCELERATION_ARB 0x2027 303#define WGL_TYPE_RGBA_ARB 0x202B 304#elif defined(__EMSCRIPTEN__) 305#else 306typedef GLXContext (*glXCreateContextAttribsARBProc)(Display *, GLXFBConfig, 307 GLXContext, Bool, 308 const int *); 309#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 310#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 311#endif 312 313#define DEFINE_GL(ret, name, ...) \ 314 typedef ret name##Proc(__VA_ARGS__); \ 315 static name##Proc *name = 0 316 317#if !defined(__EMSCRIPTEN__) 318#define GL_VERSION 0x1F02 319#define GL_SHADING_LANGUAGE_VERSION 0x8B8C 320 321/* data types */ 322#define GL_BYTE 0x1400 323#define GL_UNSIGNED_BYTE 0x1401 324#define GL_SHORT 0x1402 325#define GL_UNSIGNED_SHORT 0x1403 326#define GL_INT 0x1404 327#define GL_UNSIGNED_INT 0x1405 328#define GL_FLOAT 0x1406 329#define GL_2_BYTES 0x1407 330#define GL_3_BYTES 0x1408 331#define GL_4_BYTES 0x1409 332#define GL_DOUBLE 0x140A 333 334/* Clear buffer bits */ 335#define GL_DEPTH_BUFFER_BIT 0x00000100 336#define GL_ACCUM_BUFFER_BIT 0x00000200 337#define GL_STENCIL_BUFFER_BIT 0x00000400 338#define GL_COLOR_BUFFER_BIT 0x00004000 339 340#define GL_RGB 0x1907 341#define GL_RGBA 0x1908 342 343/* bgra */ 344#define GL_BGR 0x80E0 345#define GL_BGRA 0x80E1 346 347/* Primitives */ 348#define GL_POINTS 0x0000 349#define GL_LINES 0x0001 350#define GL_TRIANGLES 0x0004 351 352#define GL_ARRAY_BUFFER 0x8892 353#define GL_ELEMENT_ARRAY_BUFFER 0x8893 354 355#define GL_STREAM_DRAW 0x88E0 356#define GL_STREAM_READ 0x88E1 357#define GL_STREAM_COPY 0x88E2 358#define GL_STATIC_DRAW 0x88E4 359#define GL_STATIC_READ 0x88E5 360#define GL_STATIC_COPY 0x88E6 361#define GL_DYNAMIC_DRAW 0x88E8 362#define GL_DYNAMIC_READ 0x88E9 363#define GL_DYNAMIC_COPY 0x88EA 364 365#define GL_TEXTURE_2D 0x0DE1 366// #define GL_TEXTURE_MIN_FILTER 0x2800 367// #define GL_TEXTURE_MAG_FILTER 0x2801 368#define GL_TEXTURE_WRAP_S 0x2802 369#define GL_TEXTURE_WRAP_T 0x2803 370 371#define GL_NEAREST 0x2600 372#define GL_REPEAT 0x2901 373#define GL_CLAMP 0x2900 374 375#define GL_CLAMP_TO_EDGE 0x812F /* 1.2 */ 376#define GL_CLAMP_TO_BORDER 0x812D /* 1.3 */ 377 378// Core 379// DEFINE_GL(void, glClearColor, float, float, float, float); 380// DEFINE_GL(void, glClear, GLenum); 381 382// Transformation 383// DEFINE_GL(void, glViewport, GLint, GLint, GLint, GLint); 384 385// VAO 386DEFINE_GL(void, glGenVertexArrays, GLsizei, GLuint *); // glGenVertexArrays 387DEFINE_GL(void, glBindVertexArray, GLuint); // glBindVertexArray 388DEFINE_GL(void, glDeleteVertexArrays, GLsizei, 389 GLuint *); // glDeleteVertexArrays 390DEFINE_GL(void, glVertexAttribPointer, GLuint, GLint, GLuint, GLint, GLint, 391 const void *); 392DEFINE_GL(void, glEnableVertexAttribArray, GLuint); 393DEFINE_GL(void, glDisableVertexAttribArray, GLuint); 394 395// Buffers 396DEFINE_GL(void, glGenBuffers, GLsizei, GLuint *); // glGenBuffers 397DEFINE_GL(void, glBindBuffer, GLenum, GLuint); // glBindBuffer 398DEFINE_GL(void, glDeleteBuffers, GLsizei, GLuint *); // glDeleteBuffers 399DEFINE_GL(void, glBufferData, GLenum, GLsizei, const void *, 400 GLenum); // glBufferData(GLenum target, GLsizeptr size, const void* 401 // data, GLenum usage) 402DEFINE_GL(void, glBufferSubData, GLenum, GLsizei, GLsizei, 403 const void *); // glBufferSubData(GLenum target, GLintptr offset, 404 // GLsizeiptr, size, const void* data) 405 406// DEFINE_GL(void, glDrawArrays, GLenum, GLint, GLsizei); // glDrawArrays 407 408// SHADERS 409#define GL_FRAGMENT_SHADER 0x8B30 410#define GL_VERTEX_SHADER 0x8B31 411 412#define GL_COMPILE_STATUS 0x8B81 413#define GL_LINK_STATUS 0x8B82 414 415DEFINE_GL(GLuint, glCreateShader, GLenum); // glCreateShader 416DEFINE_GL(void, glShaderSource, GLuint, GLsizei, const char **, 417 const GLint *); // glShaderSource 418DEFINE_GL(void, glCompileShader, GLuint); // glCompileShader 419 420#define GL_LINK_STATUS 0x8B82 421DEFINE_GL(void, glGetShaderiv, GLuint, GLenum, GLint *); // glGetShaderiv 422const int t = GL_LINK_STATUS; 423DEFINE_GL(void, glGetShaderInfoLog, GLuint, GLsizei, GLsizei *, 424 char *); // glGetShaderInfoLog 425DEFINE_GL(void, glDeleteShader, GLuint); // glDeleteShader 426DEFINE_GL(GLuint, glCreateProgram, void); // glCreateProgram 427DEFINE_GL(void, glAttachShader, GLuint, GLuint); // glAttachShader 428DEFINE_GL(void, glLinkProgram, GLuint); // glLinkProgram 429DEFINE_GL(void, glGetProgramiv, GLuint, GLenum, GLint *); // glGetProgramiv 430DEFINE_GL(void, glGetProgramInfoLog, GLuint, GLsizei, GLsizei *, 431 char *); // glGetProgramInfoLog 432DEFINE_GL(void, glUseProgram, GLuint); // glUseProgram 433DEFINE_GL(void, glDeleteProgram, GLuint); // glUseProgram 434 435DEFINE_GL(void, glGetActiveUniform, GLuint, GLuint, GLint, GLint *, GLint *, 436 GLint *, char *); 437DEFINE_GL(GLint, glGetUniformLocation, GLuint, const char *); 438 439#define DEFINE_GL_UNIFORM(X, T) \ 440 DEFINE_GL(void, glUniform1##X, GLuint, T); \ 441 DEFINE_GL(void, glUniform2##X, GLint, T, T); \ 442 DEFINE_GL(void, glUniform3##X, GLint, T, T, T); \ 443 DEFINE_GL(void, glUniform4##X, GLint, T, T, T, T); \ 444 DEFINE_GL(void, glUniform1##X##v, GLint, GLint, const T *); \ 445 DEFINE_GL(void, glUniform2##X##v, GLint, GLint, const T *); \ 446 DEFINE_GL(void, glUniform3##X##v, GLint, GLint, const T *); \ 447 DEFINE_GL(void, glUniform4##X##v, GLint, GLint, const T *) 448 449// DEFINE_GL_UNIFORM(f, float); 450// DEFINE_GL_UNIFORM(i, GLint); 451 452DEFINE_GL(void, glUniformMatrix2fv, GLint, GLint, GLint, const float *); 453DEFINE_GL(void, glUniformMatrix3fv, GLint, GLint, GLint, const float *); 454DEFINE_GL(void, glUniformMatrix4fv, GLint, GLint, GLint, const float *); 455 456DEFINE_GL(GLint, glGetAttribLocation, GLuint, const char *); 457DEFINE_GL(void, glGetActiveAttribe, GLuint, GLuint, GLint, GLint *, GLint *, 458 GLuint *, char *); 459DEFINE_GL(void, glBindAttribLocation, GLuint, GLuint, const char *); 460 461#if defined(_WIN32) 462static HMODULE _gl_sym; 463#elif defined(__EMSCRIPTEN__) 464#else 465static void *_gl_sym; 466#ifndef RTLD_LAZY 467#define RTLD_LAZY 0x00001 468#endif 469#ifndef RTLD_GLOBAL 470#define RTLD_GLOBAL 0x00100 471#endif 472#endif 473 474static void *_get_proc(const char *name); 475BITE_RESULT _load_gl(void); 476void _setup_gl(void); 477void _close_gl(void); 478#endif 479 480BITE_RESULT _init_context(be_Context *ctx, const be_Config *conf); 481BITE_RESULT _init_window(be_Window *window, const be_Config *conf); 482BITE_RESULT _init_render(be_Render *render, const be_Window *window, 483 const be_Config *conf); 484void _poll_events(be_Context *ctx); 485 486#if defined(_WIN32) 487LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { 488 be_Context *ctx = (be_Context *)GetWindowLongPtr(hwnd, GWLP_USERDATA); 489 be_Event e; 490 e.type = 0; 491 be_EventCallback fn = NULL; 492 switch (msg) { 493 case WM_CREATE: return 0; 494 case WM_CLOSE: { 495 e.type = BITE_WINDOW_CLOSE; 496 } break; 497 case WM_DESTROY: 498 PostQuitMessage(0); 499 break; 500 case WM_SYSKEYDOWN: 501 case WM_KEYDOWN: { 502 e.type = BITE_KEY_PRESSED; 503 e.key.keycode = keys[(int)wParam]; 504 } break; 505 case WM_SYSKEYUP: 506 case WM_KEYUP: { 507 e.type = BITE_KEY_RELEASED; 508 e.key.keycode = keys[(int)wParam]; 509 printf("KeyPressed: %d\n", e.key.keycode); 510 } break; 511 default: 512 return DefWindowProc(hwnd, msg, wParam, lParam); 513 } 514 515 if (ctx) 516 fn = ctx->callbacks[e.type]; 517 if (fn) 518 fn(ctx, &e); 519 printf("Teste\n"); 520 return 0; 521} 522#endif 523 524void bite_simple_triangle(be_Context *ctx) { 525 glClearColor(0.3f, 0.4f, 0.4f, 1.f); 526 glClear(GL_COLOR_BUFFER_BIT); 527 // fprintf(stdout, "VAO: %d\n", ctx->render.vao); 528#if !defined(__EMSCRIPTEN__) 529 glBindVertexArray(ctx->render.vao); 530#else 531 glBindBuffer(GL_ARRAY_BUFFER, ctx->render.vbo); 532#endif 533 glDrawArrays(GL_TRIANGLES, 0, 3); 534#if !defined(__EMSCRIPTEN__) 535 glBindVertexArray(0); 536#else 537 glBindBuffer(GL_ARRAY_BUFFER, 0); 538#endif 539 // glBegin(GL_TRIANGLES); 540 // glColor3f(1.f, 0.f, 0.f); 541 // glVertex2f(0.f, 0.5f); 542 // glColor3f(0.f, 1.f, 0.f); 543 // glVertex2f(-0.5f, -0.5f); 544 // glColor3f(0.f, 0.f, 1.f); 545 // glVertex2f(0.5f, -0.5f); 546 // glEnd(); 547} 548 549be_Config bite_init_config(const char *title, int w, int h) { 550 be_Config c = {0}; 551 title = title != NULL ? title : "bitEngine " BITE_VERSION; 552 size_t len = strlen(title); 553 memcpy(c.window.title, title, len); 554 c.window.width = w; 555 c.window.height = h; 556 return c; 557} 558 559be_Context *bite_create(const be_Config *conf) { 560 conf = conf ? conf : &(_conf); 561 be_Context *ctx = malloc(sizeof(*ctx)); 562 if (!ctx) { 563 fprintf(stderr, "Failed to alloc memory for context\n"); 564 return NULL; 565 } 566 int mag, min; 567 // glGetIntegerv(GL_MAJOR_VERSION, &mag); 568 // glGetIntegerv(GL_MINOR_VERSION, &min); 569 // printf("OpenGL loaded: %d.%d\n", mag, min); 570 ctx->running = 1; 571 for (int i = 0; i < BITE_EVENTS; i++) { 572 ctx->callbacks[i] = NULL; 573 } 574 if (_init_context(ctx, conf) < 0) { 575 free(ctx); 576 return NULL; 577 } 578 const char *ver = (const char*)glGetString(GL_VERSION); 579 printf("OpenGL loaded: %s\n", ver); 580 return ctx; 581} 582 583void bite_destroy(be_Context *ctx) { 584 if (!ctx) 585 return; 586 be_Window *window = &(ctx->window); 587 be_Render *render = &(ctx->render); 588#if defined(_WIN32) 589 wglMakeCurrent(NULL, NULL); 590 wglDeleteContext(render->gl_context); 591 ReleaseDC(window->handle, window->dev_context); 592 DestroyWindow(window->handle); 593#elif defined(__EMSCRIPTEN__) 594 emscripten_webgl_destroy_context(render->gl_context); 595#else 596 glXDestroyContext(window->display, render->gl_context); 597 XDestroyWindow(window->display, window->handle); 598 XCloseDisplay(window->display); 599#endif 600 free(ctx); 601} 602 603void bite_register_callback(be_Context *ctx, int type, 604 be_EventCallback callback) { 605 if (!ctx) 606 return; 607 if (type < BITE_QUIT || type >= BITE_EVENTS) 608 return; 609 ctx->callbacks[type] = callback; 610} 611 612int bite_should_close(be_Context *ctx) { 613 if (!ctx) 614 return 1; 615 return !(ctx->running); 616} 617 618void bite_set_should_close(be_Context *ctx, int should_close) { 619 if (!ctx) 620 return; 621 ctx->running = !should_close; 622} 623 624void bite_poll_events(be_Context *ctx) { 625 if (!ctx) 626 return; 627 _poll_events(ctx); 628} 629 630void bite_swap(be_Context *ctx) { 631 if (!ctx) 632 return; 633 be_Window *window = &(ctx->window); 634#if defined(_WIN32) 635 SwapBuffers(window->dev_context); 636#elif defined(__EMSCRIPTEN__) 637 emscripten_webgl_commit_frame(); 638#else 639 glXSwapBuffers(window->display, window->handle); 640#endif 641} 642 643/********************* 644 * Window 645 *********************/ 646void bite_set_window_width(be_Context *ctx, int width) {} 647 648int bite_get_window_width(be_Context *ctx) { 649 if (!ctx) 650 return -1; 651 return ctx->window.width; 652} 653 654/********************* 655 * Render 656 *********************/ 657 658static GLuint _compile_shader(GLenum type, const char *src) { 659 GLuint shader = glCreateShader(type); 660 glShaderSource(shader, 1, &src, NULL); 661 glCompileShader(shader); 662 663 int success; 664 glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 665 if (!success) { 666 char info_log[512]; 667 glGetShaderInfoLog(shader, 512, NULL, info_log); 668 fprintf(stderr, "Failed to compile shader: %s\n", info_log); 669 glDeleteShader(shader); 670 return 0; 671 } 672 673 return shader; 674} 675 676static GLuint _create_program(GLuint vert, GLuint frag) { 677#if 1 678 GLuint program = glCreateProgram(); 679 glAttachShader(program, vert); 680 glAttachShader(program, frag); 681 glLinkProgram(program); 682 683 int success; 684 glGetProgramiv(program, GL_LINK_STATUS, &success); 685 if (!success) { 686 char info_log[512]; 687 glGetProgramInfoLog(program, 512, NULL, info_log); 688 fprintf(stderr, "Failed to link program: %s\n", info_log); 689 glDeleteProgram(program); 690 return 0; 691 } 692 693 return program; 694#endif 695 return 0; 696} 697 698be_Texture *bite_create_texture(int width, int height, int format, void *data) { 699 be_Texture *texture = (be_Texture *)malloc(sizeof(*texture)); 700 if (!texture) { 701 fprintf(stderr, "Failed to alloc memory for texture\n"); 702 return NULL; 703 } 704 texture->filter[0] = GL_NEAREST; 705 texture->filter[1] = GL_NEAREST; 706 texture->wrap[0] = GL_CLAMP_TO_EDGE; 707 texture->wrap[1] = GL_CLAMP_TO_EDGE; 708 texture->width = width; 709 texture->height = height; 710 711 glGenTextures(1, &(texture->handle)); 712 glBindTexture(GL_TEXTURE_2D, texture->handle); 713 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, 714 GL_UNSIGNED_BYTE, data); 715 716 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texture->filter[0]); 717 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture->filter[1]); 718 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texture->wrap[0]); 719 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texture->wrap[1]); 720 glBindTexture(GL_TEXTURE_2D, 0); 721 return texture; 722} 723 724be_Shader *bite_create_shader(const char *vert_src, const char *frag_src) { 725 be_Shader *shader = NULL; 726 GLuint vert, frag; 727 vert = _compile_shader(GL_VERTEX_SHADER, vert_src); 728 if (vert <= 0) 729 return shader; 730 frag = _compile_shader(GL_FRAGMENT_SHADER, frag_src); 731 if (frag <= 0) 732 return shader; 733 734 GLuint program = _create_program(vert, frag); 735 if (program <= 0) 736 return shader; 737 shader = malloc(sizeof(*shader)); 738 shader->handle = program; 739 740 return shader; 741} 742 743void bite_render_clear_color(float r, float g, float b, float a) { 744 glClearColor(r, g, b, a); 745} 746 747void bite_render_clear(void) { glClear(GL_COLOR_BUFFER_BIT); } 748 749void bite_bind_framebuffer(be_Framebuffer *fbo) { 750#if 0 751 if (!fbo) glBindFramebuffer(GL_FRAMEBUFFER, 0); 752 else glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); 753#endif 754} 755 756void bite_bind_texture(be_Texture *tex) { 757 if (!tex) 758 glBindTexture(GL_TEXTURE_2D, 0); 759 else 760 glBindTexture(GL_TEXTURE_2D, tex->handle); 761} 762 763void bite_use_shader(be_Shader *shader) { 764 if (!shader) 765 glUseProgram(0); 766 else 767 glUseProgram(shader->handle); 768} 769 770/********************* 771 * Timer 772 *********************/ 773void bite_sleep(be_u64 ms) { 774#if defined(_WIN32) 775 Sleep(ms); 776#elif defined(__EMSCRIPTEN__) 777 emscripten_sleep((be_u32)ms); 778#else 779 sleep(ms / 1000); 780#endif 781} 782 783be_u64 bite_tick(void) { 784 be_u64 tick = 0; 785#if defined(_WIN32) 786 LARGE_INTEGER freq, count; 787 QueryPerformanceFrequency(&freq); 788 QueryPerformanceCounter(&count); 789 tick = (be_u64)(count.QuadPart * 1000.0 / freq.QuadPart); 790#else 791 struct timespec time; 792 clock_gettime(CLOCK_REALTIME, &time); 793 tick = time.tv_sec * 1000 + (time.tv_nsec / 1000000); 794#endif 795 return tick; 796} 797 798/********************* 799 * Internal 800 *********************/ 801 802// static void init_opengl_extensions(be_Context* ctx); 803 804#if defined(_WIN32) 805static void init_opengl_extensions(void) { 806 WNDCLASSA window_class = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, 807 .lpfnWndProc = DefWindowProcA, 808 .hInstance = GetModuleHandle(0), 809 .lpszClassName = "Dummy_WGL_window"}; 810 811 if (!RegisterClassA(&window_class)) { 812 fprintf(stderr, "Failed to register dummy OpenGL window\n"); 813 exit(EXIT_FAILURE); 814 } 815 816 HWND dummy_window = 817 CreateWindowExA(0, window_class.lpszClassName, "Dummy OpenGL Window", 0, 818 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 819 CW_USEDEFAULT, 0, 0, window_class.hInstance, 0); 820 821 if (!dummy_window) { 822 fprintf(stderr, "Failed to create dummy OpenGL window\n"); 823 exit(EXIT_FAILURE); 824 } 825 826 HDC dummy_dc = GetDC(dummy_window); 827 828 PIXELFORMATDESCRIPTOR pfd = {.nSize = sizeof(pfd), 829 .nVersion = 1, 830 .iPixelType = PFD_TYPE_RGBA, 831 .dwFlags = PFD_DRAW_TO_WINDOW | 832 PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 833 .cColorBits = 32, 834 .cAlphaBits = 8, 835 .iLayerType = PFD_MAIN_PLANE, 836 .cDepthBits = 24, 837 .cStencilBits = 8}; 838 839 int pixel_format = ChoosePixelFormat(dummy_dc, &pfd); 840 if (!pixel_format) { 841 fprintf(stderr, "Failed to find a suitable format\n"); 842 exit(EXIT_FAILURE); 843 } 844 if (!SetPixelFormat(dummy_dc, pixel_format, &pfd)) { 845 fprintf(stderr, "Failed to set the pixel format\n"); 846 exit(EXIT_FAILURE); 847 } 848 849 HGLRC dummy_context = wglCreateContext(dummy_dc); 850 if (!dummy_context) { 851 fprintf(stderr, "Failed to create dummy OpenGL context\n"); 852 exit(EXIT_FAILURE); 853 } 854 855 if (!wglMakeCurrent(dummy_dc, dummy_context)) { 856 fprintf(stderr, "Failed to activate dummy OpenGL context\n"); 857 exit(EXIT_FAILURE); 858 } 859 wglCreateContextAttribsARB = 860 (wglCreateContextAttribsARBProc *)wglGetProcAddress( 861 "wglCreateContextAttribsARB"); 862 wglChoosePixelFormatARB = (wglChoosePixelFormatARBProc *)wglGetProcAddress( 863 "wglChoosePixelFormatARB"); 864 865 printf("functions: %p %p\n", wglCreateContextAttribsARB, 866 wglChoosePixelFormatARB); 867 868 wglMakeCurrent(dummy_dc, 0); 869 wglDeleteContext(dummy_context); 870 ReleaseDC(dummy_window, dummy_dc); 871 DestroyWindow(dummy_window); 872} 873#else 874static BITE_BOOL is_extension_supported(const char *extList, 875 const char *extension) { 876 const char *start; 877 const char *where, *terminator; 878 879 /* Extension names should not have spaces. */ 880 where = strchr(extension, ' '); 881 if (where || *extension == '\0') 882 return BITE_FALSE; 883 884 /* It takes a bit of care to be fool-proof about parsing the 885 OpenGL extensions string. Don't be fooled by sub-strings, 886 etc. */ 887 for (start = extList;;) { 888 where = strstr(start, extension); 889 890 if (!where) 891 break; 892 893 terminator = where + strlen(extension); 894 895 if (where == start || *(where - 1) == ' ') 896 if (*terminator == ' ' || *terminator == '\0') 897 return BITE_TRUE; 898 899 start = terminator; 900 } 901 return BITE_FALSE; 902} 903#endif 904 905BITE_RESULT _init_context(be_Context *ctx, const be_Config *conf) { 906 if (_init_window(&(ctx->window), conf) != BITE_OK) 907 return BITE_ERROR; 908#if defined(_WIN32) 909 SetWindowLongPtr(ctx->window.handle, GWLP_USERDATA, (LONG_PTR)ctx); 910#endif 911 if (_init_render(&(ctx->render), &(ctx->window), conf) != BITE_OK) 912 return BITE_ERROR; 913 be_Render *render = &(ctx->render); 914 915 float vertices[] = {0.f, 0.5f, 1.f, 0.f, 0.f, 1.f, -0.5f, -0.5f, 0.f, 916 1.f, 0.f, 1.f, 0.5f, -0.5f, 0.f, 0.f, 1.f, 1.f}; 917 918#if !defined(__EMSCRIPTEN__) 919 glGenVertexArrays(1, &(render->vao)); 920 glBindVertexArray(render->vao); 921#endif 922 glGenBuffers(1, &(render->vbo)); 923 glBindBuffer(GL_ARRAY_BUFFER, render->vbo); 924 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 925 926 glEnableVertexAttribArray(0); 927 glEnableVertexAttribArray(1); 928 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)0); 929 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(float), 930 (void *)(2 * sizeof(float))); 931 // glBindBuffer(GL_ARRAY_BUFFER, 0); 932#if !defined(__EMSCRIPTEN__) 933 glBindVertexArray(0); 934#endif 935 return BITE_OK; 936} 937 938BITE_RESULT _init_window(be_Window *window, const be_Config *conf) { 939#if defined(_WIN32) 940 HWND handle; 941 HMODULE hInstance = GetModuleHandle(0); 942 943 const TCHAR windowClass[] = _T("bitEngine"); 944 945 WNDCLASSEX wc; 946 wc.cbSize = sizeof(WNDCLASSEX); 947 wc.style = CS_HREDRAW | CS_VREDRAW; 948 wc.lpfnWndProc = WindowProc; 949 wc.cbClsExtra = 0; 950 wc.cbWndExtra = 0; 951 wc.hInstance = hInstance; 952 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 953 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 954 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 955 wc.lpszMenuName = NULL; 956 wc.lpszClassName = windowClass; 957 wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 958 959 if (!RegisterClassEx(&wc)) { 960 MessageBox(NULL, _T("Call to RegisterClassEx failed"), _T("bitEngine"), 961 NULL); 962 return BITE_ERROR; 963 } 964 965 handle = CreateWindow(windowClass, conf->window.title, WS_OVERLAPPEDWINDOW, 966 CW_USEDEFAULT, CW_USEDEFAULT, conf->window.width, 967 conf->window.height, NULL, NULL, hInstance, NULL); 968 if (!handle) { 969 MessageBox(NULL, _T("Class to CreateWindow failed"), _T("bitEngine"), NULL); 970 return BITE_ERROR; 971 } 972 window->handle = handle; 973 window->dev_context = GetDC(handle); 974 975 ShowWindow(handle, SW_SHOWDEFAULT); 976 UpdateWindow(handle); 977#elif (__EMSCRIPTEN__) 978#else 979 Display *dpy; 980 Window handle; 981 dpy = XOpenDisplay(NULL); 982 if (dpy == NULL) { 983 fprintf(stderr, "Could not open X11 display\n"); 984 return BITE_ERROR; 985 } 986 int scrId = DefaultScreen(dpy); 987 988 static int visual_attribs[] = { 989 GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, 990 GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, 991 GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, 992 GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, GLX_DOUBLEBUFFER, True, 993 // GLX_SAMPLE_BUFFERS , 1, 994 // GLX_SAMPLES , 4, 995 None}; 996 997 GLint major, minor; 998 glXQueryVersion(dpy, &major, &minor); 999 if ((major == 1 && minor < 3) || (major < 1)) { 1000 fprintf(stderr, "Invalid GLX version\n"); 1001 XCloseDisplay(dpy); 1002 return BITE_ERROR; 1003 } 1004 1005 int fbcount; 1006 GLXFBConfig *fbc = glXChooseFBConfig(dpy, scrId, visual_attribs, &fbcount); 1007 if (!fbc) { 1008 fprintf(stderr, "Failed to retrieve a framebuffer config\n"); 1009 return BITE_ERROR; 1010 } 1011 1012 int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999; 1013 1014 int i; 1015 for (i = 0; i < fbcount; ++i) { 1016 XVisualInfo *vi = glXGetVisualFromFBConfig(dpy, fbc[i]); 1017 if (vi) { 1018 int samp_buf, samples; 1019 glXGetFBConfigAttrib(dpy, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); 1020 glXGetFBConfigAttrib(dpy, fbc[i], GLX_SAMPLES, &samples); 1021 1022 // printf( " Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d," 1023 // " SAMPLES = %d\n", 1024 // i, vi -> visualid, samp_buf, samples ); 1025 1026 if (best_fbc < 0 || samp_buf && samples > best_num_samp) 1027 best_fbc = i, best_num_samp = samples; 1028 if (worst_fbc < 0 || !samp_buf || samples < worst_num_samp) 1029 worst_fbc = i, worst_num_samp = samples; 1030 } 1031 XFree(vi); 1032 } 1033 GLXFBConfig bestFbc = fbc[best_fbc]; 1034 XFree(fbc); 1035 1036 XVisualInfo *vi = glXGetVisualFromFBConfig(dpy, bestFbc); 1037 XSetWindowAttributes swa; 1038 Colormap map; 1039 swa.colormap = 1040 XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone); 1041 swa.background_pixmap = None; 1042 swa.border_pixel = 0; 1043 swa.event_mask = ExposureMask | StructureNotifyMask; 1044 1045 handle = 1046 XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, conf->window.width, 1047 conf->window.height, 0, vi->depth, InputOutput, vi->visual, 1048 CWBorderPixel | CWColormap | CWEventMask, &swa); 1049 1050 if (!handle) { 1051 fprintf(stderr, "Failed to create X11 window\n"); 1052 return BITE_ERROR; 1053 } 1054 1055 XFree(vi); 1056 XSelectInput(dpy, handle, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask); 1057 XClearWindow(dpy, handle); 1058 XStoreName(dpy, handle, conf->window.title); 1059 XMapWindow(dpy, handle); 1060 1061 window->handle = handle; 1062 window->display = dpy; 1063 window->map = swa.colormap; 1064 window->fbconf = bestFbc; 1065#endif 1066 window->width = conf->window.width; 1067 window->height = conf->window.height; 1068 return BITE_OK; 1069} 1070 1071BITE_RESULT _init_render(be_Render *render, const be_Window *window, 1072 const be_Config *conf) { 1073#if defined(_WIN32) 1074 init_opengl_extensions(); 1075 HDC hdc = window->dev_context; 1076 int pixel_format_attribs[] = {WGL_DRAW_TO_WINDOW_ARB, 1077 GL_TRUE, 1078 WGL_SUPPORT_OPENGL_ARB, 1079 GL_TRUE, 1080 WGL_DOUBLE_BUFFER_ARB, 1081 GL_TRUE, 1082 WGL_ACCELERATION_ARB, 1083 WGL_FULL_ACCELERATION_ARB, 1084 WGL_PIXEL_TYPE_ARB, 1085 WGL_TYPE_RGBA_ARB, 1086 WGL_COLOR_BITS_ARB, 1087 32, 1088 WGL_DEPTH_BITS_ARB, 1089 24, 1090 WGL_STENCIL_BITS_ARB, 1091 8, 1092 0, 1093 0}; 1094 1095 int pixel_format; 1096 UINT num_formats; 1097 wglChoosePixelFormatARB(hdc, pixel_format_attribs, 0, 1, &pixel_format, 1098 &num_formats); 1099 if (!num_formats) { 1100 MessageBox(NULL, _T("Failed to set Modern OpenGL pixel format"), 1101 _T("bitEngine"), NULL); 1102 DestroyWindow(window->handle); 1103 return BITE_ERROR; 1104 } 1105 1106 PIXELFORMATDESCRIPTOR pfd; 1107 DescribePixelFormat(hdc, pixel_format, sizeof(pfd), &pfd); 1108 if (!SetPixelFormat(hdc, pixel_format, &pfd)) { 1109 MessageBox(NULL, _T("Failed to set Modern OpenGL pixel format\n"), 1110 _T("bitEngine"), NULL); 1111 DestroyWindow(window->handle); 1112 return BITE_ERROR; 1113 } 1114 1115 int gl_attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 1116 3, 1117 WGL_CONTEXT_MINOR_VERSION_ARB, 1118 0, 1119 WGL_CONTEXT_PROFILE_MASK_ARB, 1120 WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 1121 0, 1122 0}; 1123 1124 HGLRC hglrc = wglCreateContextAttribsARB(hdc, 0, gl_attribs); 1125 if (!hglrc) { 1126 MessageBox(NULL, _T("Failed to create Modern OpenGL context"), 1127 _T("bitEngine"), NULL); 1128 DestroyWindow(window->handle); 1129 return BITE_ERROR; 1130 } 1131 wglMakeCurrent(hdc, hglrc); 1132 1133 if (_load_gl() != BITE_OK) { 1134 MessageBox(NULL, _T("Failed to init OpenGL loader"), _T("bitEngine"), NULL); 1135 DestroyWindow(window->handle); 1136 return BITE_ERROR; 1137 } 1138 _setup_gl(); 1139 _close_gl(); 1140#elif defined(__EMSCRIPTEN__) 1141 EmscriptenWebGLContextAttributes attr; 1142 emscripten_webgl_init_context_attributes(&attr); 1143 attr.alpha = 0; 1144 render->gl_context = emscripten_webgl_create_context("#canvas", &attr); 1145 emscripten_webgl_make_context_current(render->gl_context); 1146#else 1147 Display *dpy = window->display; 1148 int scrId = DefaultScreen(dpy); 1149 const char *glxExts = glXQueryExtensionsString(dpy, scrId); 1150 glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; 1151 glXCreateContextAttribsARB = 1152 (glXCreateContextAttribsARBProc)glXGetProcAddressARB( 1153 (const GLubyte *)"glXCreateContextAttribsARB"); 1154 1155 GLXContext ctx = 0; 1156 1157 if (!glXCreateContextAttribsARB) { 1158 fprintf(stderr, "Failed to load glXCreateContextAttribsARB(), loading " 1159 "legacy OpenGL context\n"); 1160 ctx = glXCreateNewContext(dpy, window->fbconf, GLX_RGBA_TYPE, 0, True); 1161 } else { 1162 int context_attribs[] = {GLX_CONTEXT_MAJOR_VERSION_ARB, 1163 2, 1164 GLX_CONTEXT_MINOR_VERSION_ARB, 1165 1, 1166 GLX_CONTEXT_PROFILE_MASK_ARB, 1167 GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 1168 None}; 1169 1170 ctx = glXCreateContextAttribsARB(dpy, window->fbconf, 0, True, 1171 context_attribs); 1172 XSync(dpy, False); 1173 if (!ctx) { 1174 fprintf(stderr, "Failed to create 3.0 OpenGL context\n"); 1175 XDestroyWindow(dpy, window->handle); 1176 XFreeColormap(dpy, window->map); 1177 XCloseDisplay(dpy); 1178 return BITE_ERROR; 1179 } 1180 glXMakeCurrent(dpy, window->handle, ctx); 1181 render->gl_context = ctx; 1182 if (_load_gl() != BITE_OK) { 1183 fprintf(stderr, "Failed to init OpenGL loader\n"); 1184 XDestroyWindow(dpy, window->handle); 1185 XFreeColormap(dpy, window->map); 1186 XCloseDisplay(dpy); 1187 return BITE_ERROR; 1188 } 1189 _setup_gl(); 1190 _close_gl(); 1191 } 1192#endif 1193 return BITE_OK; 1194} 1195 1196#if 0 1197int _init_context(be_Context* ctx, const be_Config* conf) { 1198#if defined(_WIN32) 1199 HWND handle; 1200 HMODULE hInstance = GetModuleHandle(0); 1201 1202 const TCHAR windowClass[] = _T("bitEngine"); 1203 1204 WNDCLASSEX wc; 1205 wc.cbSize = sizeof(WNDCLASSEX); 1206 wc.style = CS_HREDRAW | CS_VREDRAW; 1207 wc.lpfnWndProc = WindowProc; 1208 wc.cbClsExtra = 0; 1209 wc.cbWndExtra = 0; 1210 wc.hInstance = hInstance; 1211 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 1212 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 1213 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 1214 wc.lpszMenuName = NULL; 1215 wc.lpszClassName = windowClass; 1216 wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 1217 1218 if (!RegisterClassEx(&wc)) { 1219 MessageBox(NULL, 1220 _T("Call to RegisterClassEx failed"), 1221 _T("bit Engine"), 1222 NULL); 1223 fprintf(stderr, "Error code: %d\n", GetLastError()); 1224 return -1; 1225 } 1226 1227 handle = CreateWindow( 1228 windowClass, 1229 conf->window.title, 1230 WS_OVERLAPPEDWINDOW, 1231 CW_USEDEFAULT, CW_USEDEFAULT, 1232 conf->window.width, conf->window.height, 1233 NULL, NULL, hInstance, ctx 1234 ); 1235 if (!handle) { 1236 MessageBox(NULL, 1237 _T("Call to CreateWindow failed"), 1238 _T("bit Engine"), 1239 NULL); 1240 fprintf(stderr, "Error code: %d\n", GetLastError()); 1241 return -1; 1242 } 1243 SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)ctx); 1244 1245 HDC hdc = GetDC(handle); 1246 1247 init_opengl_extensions(); 1248 1249 int pixel_format_attribs[] = { 1250 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, 1251 WGL_SUPPORT_OPENGL_ARB, GL_TRUE, 1252 WGL_DOUBLE_BUFFER_ARB, GL_TRUE, 1253 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, 1254 WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, 1255 WGL_COLOR_BITS_ARB, 32, 1256 WGL_DEPTH_BITS_ARB, 24, 1257 WGL_STENCIL_BITS_ARB, 8, 1258 0 1259 }; 1260 1261 int pixel_format; 1262 UINT num_formats; 1263 wglChoosePixelFormatARB(hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats); 1264 if (!num_formats) { 1265 fprintf(stderr, "Failed to set Modern OpenGL pixel format\n"); 1266 DestroyWindow(handle); 1267 return -1; 1268 } 1269 1270 PIXELFORMATDESCRIPTOR pfd; 1271 DescribePixelFormat(hdc, pixel_format, sizeof(pfd), &pfd); 1272 if (!SetPixelFormat(hdc, pixel_format, &pfd)) { 1273 fprintf(stderr, "Failed to set Modern OpenGL pixel format\n"); 1274 DestroyWindow(handle); 1275 return -1; 1276 } 1277 1278 int gl_attribs[] = { 1279 WGL_CONTEXT_MAJOR_VERSION_ARB, 2, 1280 WGL_CONTEXT_MINOR_VERSION_ARB, 1, 1281 WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 1282 0 1283 }; 1284 1285 HGLRC hglrc = wglCreateContextAttribsARB(hdc, 0, gl_attribs); 1286 if (!hglrc) { 1287 fprintf(stderr, "Failed to create Modern OpenGL context\n"); 1288 DestroyWindow(handle); 1289 return -1; 1290 } 1291 wglMakeCurrent(hdc, hglrc); 1292 1293 // ctx = malloc(sizeof(*ctx)); 1294 be_Window* window = &(ctx->window); 1295 window->handle = handle; 1296 window->dev_context = hdc; 1297 1298 ShowWindow(handle, SW_SHOWDEFAULT); 1299 UpdateWindow(handle); 1300#elif defined(__EMSCRIPTEN__) 1301 be_Window* window = &(ctx->window); 1302 EmscriptenWebGLContextAttributes attr; 1303 emscripten_webgl_init_context_attributes(&attr); 1304 attr.alpha = 0; 1305 ctx->window.handle = emscripten_webgl_create_context("#canvas", &attr); 1306 emscripten_webgl_make_context_current(window->handle); 1307#else 1308 Display* dpy; 1309 Window handle; 1310 Screen* scr; 1311 int scrId; 1312 dpy = XOpenDisplay(NULL); 1313 if (dpy == NULL) { 1314 fprintf(stderr, "Could not open X11 display\n"); 1315 return -1; 1316 } 1317 scr = DefaultScreenOfDisplay(dpy); 1318 scrId = DefaultScreen(dpy); 1319 1320 GLint majorGLX, minorGLX; 1321 glXQueryVersion(dpy, &majorGLX, &minorGLX); 1322 if (majorGLX <= 1 && minorGLX < 2) { 1323 fprintf(stderr, "GLX 1.2 or greater is required\n"); 1324 XCloseDisplay(dpy); 1325 return -1; 1326 } else { 1327 fprintf(stdout, "GLX version: %d.%d\n", majorGLX, minorGLX); 1328 } 1329 1330 GLint glxAttribs[] = { 1331 GLX_RGBA, 1332 GLX_DOUBLEBUFFER, 1333 GLX_DEPTH_SIZE, 24, 1334 GLX_STENCIL_SIZE, 8, 1335 GLX_RED_SIZE, 8, 1336 GLX_GREEN_SIZE, 8, 1337 GLX_BLUE_SIZE, 8, 1338 GLX_SAMPLE_BUFFERS, 0, 1339 GLX_SAMPLES, 0, 1340 None 1341 }; 1342 XVisualInfo* visual = glXChooseVisual(dpy, scrId, glxAttribs); 1343 if (!visual) { 1344 fprintf(stderr, "Failed to create correct visual window\n"); 1345 XCloseDisplay(dpy); 1346 return -1; 1347 } 1348 1349 XSetWindowAttributes windowAttribs; 1350 windowAttribs.border_pixel = BlackPixel(dpy, scrId); 1351 windowAttribs.background_pixel = WhitePixel(dpy, scrId); 1352 windowAttribs.override_redirect = 1; 1353 windowAttribs.colormap = XCreateColormap(dpy, RootWindow(dpy, scrId), visual->visual, AllocNone); 1354 windowAttribs.event_mask = ExposureMask; 1355 1356 handle = XCreateWindow(dpy, RootWindowOfScreen(scr), 0, 0, conf->window.width, conf->window.height, 0, visual->depth, InputOutput, visual->visual, CWBackPixel | CWColormap | CWBorderPixel | CWEventMask, &windowAttribs); 1357 if (!handle) { 1358 fprintf(stderr, "Failed to create X11 window\n"); 1359 XCloseDisplay(dpy); 1360 return -1; 1361 } 1362 GLXContext context = glXCreateContext(dpy, visual, NULL, GL_TRUE); 1363 if (!context) { 1364 fprintf(stderr, "Failed to create GLX context\n"); 1365 XDestroyWindow(dpy, handle); 1366 XCloseDisplay(dpy); 1367 return -1; 1368 } 1369 glXMakeCurrent(dpy, handle, context); 1370 be_Window* window = &(ctx->window); 1371 window->display = dpy; 1372 window->handle = handle; 1373 window->glContext = context; 1374 XSelectInput(dpy, handle, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask); 1375 XClearWindow(dpy, handle); 1376 XMapRaised(dpy, handle); 1377 XStoreName(dpy, handle, conf->window.title); 1378#endif 1379 1380 if (_init_gl(ctx) != BITE_OK) { 1381 fprintf(stderr, "Failed to init OpenGL loader\n"); 1382 return NULL; 1383 } 1384 _setup_gl(); 1385 _close_gl(); 1386 1387 1388 ctx->window.width = conf->window.width; 1389 ctx->window.height = conf->window.height; 1390 return BITE_OK; 1391} 1392#endif 1393void _poll_events(be_Context *ctx) { 1394#if defined(_WIN32) 1395 MSG message; 1396 if (GetMessage(&message, NULL, 0, 0)) { 1397 TranslateMessage(&message); 1398 DispatchMessage(&message); 1399 } 1400#elif defined(__EMSCRIPTEN__) 1401#else 1402 XEvent ev; 1403 be_Window *window = &(ctx->window); 1404 while (XPending(window->display)) { 1405 XNextEvent(window->display, &ev); 1406 be_Event e = {0}; 1407 be_EventCallback fn = NULL; 1408 switch (ev.type) { 1409 case ClientMessage: { 1410 if (ev.xclient.data.l[0] == 1411 XInternAtom(window->display, "WM_DELETE_WINDOW", 0)) { 1412 e.type = BITE_WINDOW_CLOSE; 1413 } 1414 } break; 1415 case DestroyNotify: { 1416 e.type = BITE_QUIT; 1417 } break; 1418 case ConfigureNotify: { 1419 XConfigureEvent xce = ev.xconfigure; 1420 if ((xce.x != window->x) || (xce.y != window->y)) { 1421 window->x = xce.x; 1422 window->y = xce.y; 1423 e.type = BITE_WINDOW_MOVE; 1424 e.window.x = xce.x; 1425 e.window.y = xce.y; 1426 e.window.handle = window; 1427 } 1428 if ((xce.width != window->width) || (xce.height != window->height)) { 1429 window->width = xce.width; 1430 window->height = xce.height; 1431 e.type = BITE_WINDOW_RESIZE; 1432 e.window.x = xce.width; 1433 e.window.y = xce.height; 1434 e.window.handle = window; 1435 } 1436 } break; 1437 case KeyPress: { 1438 e.type = BITE_KEY_PRESSED; 1439 int code = ev.xkey.keycode; 1440 int keysym = XkbKeycodeToKeysym( 1441 ctx->window.display, 1442 ev.xkey.keycode, 1443 0, 1444 ev.xkey.state & ShiftMask ? 1 : 0 1445 ); 1446 e.key.keycode = keys[keysym]; 1447 printf("KeyPress: %d %d %d\n", keysym, ev.xkey.keycode, e.key.keycode); 1448 } break; 1449 case KeyRelease: { 1450 e.type = BITE_KEY_RELEASED; 1451 int keysym = XkbKeycodeToKeysym( 1452 ctx->window.display, 1453 ev.xkey.keycode, 1454 0, 1455 ev.xkey.state & ShiftMask ? 1 : 0 1456 ); 1457 e.key.keycode = keys[keysym]; 1458 } break; 1459 } 1460 fn = ctx->callbacks[e.type]; 1461 if (fn) 1462 fn(ctx, &e); 1463 } 1464#endif 1465} 1466 1467// OpenGL loader 1468 1469#if !defined(__APPLE__) && !defined(__HAIKU__) 1470void *(*_proc_address)(const char *); 1471#endif 1472 1473#define GET_GL_PROC(name) name = (name##Proc *)_get_proc(#name) 1474 1475void *_get_proc(const char *); 1476 1477BITE_RESULT _load_gl(void) { 1478#if defined(_WIN32) 1479 _gl_sym = LoadLibrary("opengl32.dll"); 1480 if (_gl_sym == NULL) { 1481 fprintf(stderr, "Failed to load OpenGL32.dll\n"); 1482 return BITE_ERROR; 1483 } 1484 _proc_address = 1485 (void *(*)(const char *))GetProcAddress(_gl_sym, "wglGetProcAddress"); 1486#elif defined(__EMSCRIPTEN__) 1487#else 1488#if defined(__APPLE__) 1489 const char *names[] = { 1490 "../Frameworks/OpenGL.framework/OpenGL", 1491 "/Library/Frameworks/OpenGL.framework/Opengl", 1492 "/System/Library/Frameworks/OpenGL.framework/OpenGL", 1493 "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", 1494 NULL, 1495 }; 1496#else 1497 const char *names[] = { 1498 "libGL.so.1", 1499 "libGL.so", 1500 NULL, 1501 }; 1502#endif 1503 int index; 1504 for (index = 0; names[index] != NULL; ++index) { 1505 _gl_sym = dlopen(names[index], RTLD_LAZY | RTLD_GLOBAL); 1506 if (_gl_sym != NULL) { 1507#if defined(__APPLE__) || defined(__HAIKU__) 1508 return BITE_OK; 1509#else 1510 _proc_address = 1511 (void *(*)(const char *))dlsym(_gl_sym, "glXGetProcAddress"); 1512 return _proc_address != NULL ? BITE_OK : BITE_ERROR; 1513#endif 1514 break; 1515 } 1516 } 1517#endif 1518 return BITE_OK; 1519} 1520 1521#if !defined(__EMSCRIPTEN__) 1522void _close_gl(void) { 1523 if (_gl_sym != NULL) { 1524#if defined(_WIN32) 1525 FreeLibrary(_gl_sym); 1526#else 1527 dlclose(_gl_sym); 1528#endif 1529 _gl_sym = NULL; 1530 } 1531} 1532 1533void _setup_gl(void) { 1534 const char *version = (const char*)glGetString(GL_VERSION); 1535 const char *glsl = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); 1536 if (!version) { 1537 fprintf(stderr, "Failed to get OpenGL version\n"); 1538 } 1539 const char *prefixes[] = {"OpenGL ES-CM ", "OpenGL ES-CL ", "OpenGL ES ", 1540 NULL}; 1541 1542 if (version) { 1543 const char *ver = version; 1544 for (int i = 0; prefixes[i] != NULL; i++) { 1545 if (strncmp(ver, prefixes[i], strlen(prefixes[i])) == 0) { 1546 ver += strlen(prefixes[i]); 1547 fprintf(stdout, "Using OpenGL ES\n"); 1548 } 1549 } 1550 } 1551 1552 fprintf(stderr, "OpenGL: %s\n", version); 1553 1554 GET_GL_PROC(glGenVertexArrays); 1555 GET_GL_PROC(glBindVertexArray); 1556 GET_GL_PROC(glDeleteVertexArrays); 1557 1558 GET_GL_PROC(glVertexAttribPointer); 1559 GET_GL_PROC(glEnableVertexAttribArray); 1560 GET_GL_PROC(glDisableVertexAttribArray); 1561 1562 GET_GL_PROC(glGenBuffers); 1563 GET_GL_PROC(glBindBuffer); 1564 GET_GL_PROC(glDeleteBuffers); 1565 GET_GL_PROC(glBufferData); 1566 GET_GL_PROC(glBufferSubData); 1567 1568 GET_GL_PROC(glCreateShader); 1569 GET_GL_PROC(glShaderSource); 1570 GET_GL_PROC(glCompileShader); 1571 GET_GL_PROC(glGetShaderiv); 1572 GET_GL_PROC(glGetShaderInfoLog); 1573 GET_GL_PROC(glDeleteShader); 1574 GET_GL_PROC(glCreateProgram); 1575 GET_GL_PROC(glAttachShader); 1576 GET_GL_PROC(glLinkProgram); 1577 GET_GL_PROC(glGetProgramiv); 1578 GET_GL_PROC(glGetProgramInfoLog); 1579 GET_GL_PROC(glUseProgram); 1580 GET_GL_PROC(glDeleteProgram); 1581} 1582 1583static inline void *_get_proc(const char *name) { 1584 void *sym = NULL; 1585 if (_gl_sym == NULL) 1586 return sym; 1587#if !defined(__APPLE__) && !defined(__HAIKU__) 1588 if (_proc_address != NULL) 1589 sym = _proc_address(name); 1590#endif 1591 if (sym == NULL) { 1592#if defined(_WIN32) || defined(__CYGWWIN__) 1593 sym = (void *)GetProcAddress(_gl_sym, name); 1594#else 1595 sym = (void *)dlsym(_gl_sym, name); 1596#endif 1597 } 1598 fprintf(stderr, "%s: %p\n", name, sym); 1599 return sym; 1600} 1601#endif