[wip] win32 gles surface using angle

This commit is contained in:
martinfouilleul 2023-01-29 01:04:24 +01:00
parent bd7e1a15f1
commit c5ae556f22
12 changed files with 758 additions and 572 deletions

View File

@ -1,6 +1,6 @@
if not exist bin mkdir bin if not exist bin mkdir bin
set INCLUDES=/I src /I src/util /I src/platform /I ext set INCLUDES=/I src /I src/util /I src/platform /I ext /I ext/angle_headers
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% /c /Fo:bin/milepost.obj src/milepost.c cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% /c /Fo:bin/milepost.obj src/milepost.c
lib bin/milepost.obj /OUT:bin/milepost.lib lib bin/milepost.obj /OUT:bin/milepost.lib

View File

@ -1,227 +1,228 @@
/************************************************************//** /************************************************************//**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 30/07/2022 * @date: 30/07/2022
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include<stdlib.h>
#include<string.h> #include<string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include<math.h>
#include"milepost.h" #include"milepost.h"
#include"win32_gl_surface.h"
#define LOG_SUBSYSTEM "Main"
#define LOG_SUBSYSTEM "Main"
unsigned int program;
unsigned int program;
const char* vshaderSource =
"#version 430\n" const char* vshaderSource =
"attribute vec4 vPosition;\n" "#version 430\n"
"uniform mat4 transform;\n" "attribute vec4 vPosition;\n"
"void main()\n" "uniform mat4 transform;\n"
"{\n" "void main()\n"
" gl_Position = transform*vPosition;\n" "{\n"
"}\n"; " gl_Position = transform*vPosition;\n"
"}\n";
const char* fshaderSource =
"#version 430\n" const char* fshaderSource =
"precision mediump float;\n" "#version 430\n"
"void main()\n" "precision mediump float;\n"
"{\n" "void main()\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" "{\n"
"}\n"; " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
void compile_shader(GLuint shader, const char* source)
{ void compile_shader(GLuint shader, const char* source)
glShaderSource(shader, 1, &source, 0); {
glCompileShader(shader); glShaderSource(shader, 1, &source, 0);
glCompileShader(shader);
int err = glGetError();
if(err) int err = glGetError();
{ if(err)
printf("gl error: %i\n", err); {
} printf("gl error: %i\n", err);
}
int status = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); int status = 0;
if(!status) glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
{ if(!status)
char buffer[256]; {
int size = 0; char buffer[256];
glGetShaderInfoLog(shader, 256, &size, buffer); int size = 0;
printf("shader error: %.*s\n", size, buffer); glGetShaderInfoLog(shader, 256, &size, buffer);
} printf("shader error: %.*s\n", size, buffer);
} }
}
int main()
{ int main()
LogLevel(LOG_LEVEL_DEBUG); {
LogLevel(LOG_LEVEL_DEBUG);
mp_init();
mp_init();
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600};
mp_window window = mp_window_create(rect, "test", 0); mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600};
mp_window window = mp_window_create(rect, "test", 0);
//NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_GL); //NOTE: create surface
mg_surface surface = mg_gl_surface_create_for_window(window);
//NOTE: init shader and gl state
GLuint vao; //NOTE: init shader and gl state
glGenVertexArrays(1, &vao); GLuint vao;
glBindVertexArray(vao); glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer); GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
GLfloat vertices[] = {
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0}; GLfloat vertices[] = {
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0};
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER); unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
program = glCreateProgram(); unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER);
program = glCreateProgram();
compile_shader(vshader, vshaderSource);
compile_shader(fshader, fshaderSource); compile_shader(vshader, vshaderSource);
compile_shader(fshader, fshaderSource);
glAttachShader(program, vshader);
glAttachShader(program, fshader); glAttachShader(program, vshader);
glLinkProgram(program); glAttachShader(program, fshader);
glLinkProgram(program);
int status = 0;
glGetProgramiv(program, GL_LINK_STATUS, &status); int status = 0;
if(!status) glGetProgramiv(program, GL_LINK_STATUS, &status);
{ if(!status)
char buffer[256]; {
int size = 0; char buffer[256];
glGetProgramInfoLog(program, 256, &size, buffer); int size = 0;
printf("link error: %.*s\n", size, buffer); glGetProgramInfoLog(program, 256, &size, buffer);
} printf("link error: %.*s\n", size, buffer);
}
glUseProgram(program);
glUseProgram(program);
mp_window_bring_to_front(window);
// mp_window_focus(window); mp_window_bring_to_front(window);
// mp_window_focus(window);
while(!mp_should_quit())
{ while(!mp_should_quit())
mp_pump_events(0); {
mp_event event = {0}; mp_pump_events(0);
while(mp_next_event(&event)) mp_event event = {0};
{ while(mp_next_event(&event))
switch(event.type) {
{ switch(event.type)
case MP_EVENT_WINDOW_CLOSE: {
{ case MP_EVENT_WINDOW_CLOSE:
mp_request_quit(); {
} break; mp_request_quit();
} break;
case MP_EVENT_WINDOW_RESIZE:
{ case MP_EVENT_WINDOW_RESIZE:
printf("resized, rect = {%f, %f, %f, %f}\n", {
event.frame.rect.x, printf("resized, rect = {%f, %f, %f, %f}\n",
event.frame.rect.y, event.frame.rect.x,
event.frame.rect.w, event.frame.rect.y,
event.frame.rect.h); event.frame.rect.w,
} break; event.frame.rect.h);
} break;
case MP_EVENT_WINDOW_MOVE:
{ case MP_EVENT_WINDOW_MOVE:
printf("moved, rect = {%f, %f, %f, %f}\n", {
event.frame.rect.x, printf("moved, rect = {%f, %f, %f, %f}\n",
event.frame.rect.y, event.frame.rect.x,
event.frame.rect.w, event.frame.rect.y,
event.frame.rect.h); event.frame.rect.w,
} break; event.frame.rect.h);
} break;
case MP_EVENT_MOUSE_MOVE:
{ case MP_EVENT_MOUSE_MOVE:
printf("mouse moved, pos = {%f, %f}, delta = {%f, %f}\n", {
event.move.x, printf("mouse moved, pos = {%f, %f}, delta = {%f, %f}\n",
event.move.y, event.move.x,
event.move.deltaX, event.move.y,
event.move.deltaY); event.move.deltaX,
} break; event.move.deltaY);
} break;
case MP_EVENT_MOUSE_WHEEL:
{ case MP_EVENT_MOUSE_WHEEL:
printf("mouse wheel, delta = {%f, %f}\n", {
event.move.deltaX, printf("mouse wheel, delta = {%f, %f}\n",
event.move.deltaY); event.move.deltaX,
} break; event.move.deltaY);
} break;
case MP_EVENT_MOUSE_ENTER:
{ case MP_EVENT_MOUSE_ENTER:
printf("mouse enter\n"); {
} break; printf("mouse enter\n");
} break;
case MP_EVENT_MOUSE_LEAVE:
{ case MP_EVENT_MOUSE_LEAVE:
printf("mouse leave\n"); {
} break; printf("mouse leave\n");
} break;
case MP_EVENT_MOUSE_BUTTON:
{ case MP_EVENT_MOUSE_BUTTON:
printf("mouse button %i: %i\n", {
event.key.code, printf("mouse button %i: %i\n",
event.key.action == MP_KEY_PRESS ? 1 : 0); event.key.code,
} break; event.key.action == MP_KEY_PRESS ? 1 : 0);
} break;
case MP_EVENT_KEYBOARD_KEY:
{ case MP_EVENT_KEYBOARD_KEY:
printf("key %i: %s\n", {
event.key.code, printf("key %i: %s\n",
event.key.action == MP_KEY_PRESS ? "press" : (event.key.action == MP_KEY_RELEASE ? "release" : "repeat")); event.key.code,
} break; event.key.action == MP_KEY_PRESS ? "press" : (event.key.action == MP_KEY_RELEASE ? "release" : "repeat"));
} break;
case MP_EVENT_KEYBOARD_CHAR:
{ case MP_EVENT_KEYBOARD_CHAR:
printf("entered char %s\n", event.character.sequence); {
} break; printf("entered char %s\n", event.character.sequence);
} break;
default:
break; default:
} break;
} }
}
mg_surface_prepare(surface);
mg_surface_prepare(surface);
glClearColor(0.3, 0.3, 1, 1);
glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.3, 0.3, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
static float alpha = 0;
//f32 aspect = frameSize.x/frameSize.y; static float alpha = 0;
f32 aspect = 800/(f32)600; //f32 aspect = frameSize.x/frameSize.y;
f32 aspect = 800/(f32)600;
glViewport(0, 0, 800, 600);
glViewport(0, 0, 800, 600);
GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0,
-sinf(alpha)/aspect, cosf(alpha), 0, 0, GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0,
0, 0, 1, 0, -sinf(alpha)/aspect, cosf(alpha), 0, 0,
0, 0, 0, 1}; 0, 0, 1, 0,
0, 0, 0, 1};
alpha += 2*M_PI/120;
alpha += 2*M_PI/120;
glUniformMatrix4fv(0, 1, false, matrix);
glUniformMatrix4fv(0, 1, false, matrix);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawArrays(GL_TRIANGLES, 0, 3);
mg_surface_present(surface);
} mg_surface_present(surface);
}
mp_terminate();
mp_terminate();
return(0);
} return(0);
}

View File

@ -1,2 +1,2 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib /out:test.exe cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib /LIBPATH:./ libEGL.dll.lib libGLESv2.dll.lib user32.lib opengl32.lib gdi32.lib /out:test.exe

View File

@ -0,0 +1,31 @@
angle install on windows
* need Python3 (can install through win app store)
* need Windows SDK
* clone depot_tools git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
or download and unzip bundle at https://storage.googleapis.com/chrome-infra/depot_tools.zip
* set depot_tools in path env variable through control panel>System and security>system>advanced system settings
* run gclient in a cmd shell
* set DEPOT_TOOLS_WIN_TOOLCHAIN=0
* mkdir angle
* cd angle
* fetch angle
* wait a million years
* fails when running python3 third_party/depot_tools/download_from_google_storage.py ...
-> open DEPS and change third_party/depot_tools with ../depot/tools
* run gclient sync to complete previous step
* gn gen out/Debug
* gn args out/Debug and edit arguments:
angle_enable_vulkan = false
angle_build_tests = false
is_component_build = false
* autoninja -C out/Debug
* wait a while
* link with libEGL.dll.lib and libGLESv2.dll.lib
* put libEGL.dll and libGLESv2.dll in same directory as executable

Binary file not shown.

Binary file not shown.

View File

@ -1,66 +1,67 @@
/************************************************************//** /************************************************************//**
* *
* @file: milepost.c * @file: milepost.c
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 13/02/2021 * @date: 13/02/2021
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
//--------------------------------------------------------------- //---------------------------------------------------------------
// utilities implementations // utilities implementations
//--------------------------------------------------------------- //---------------------------------------------------------------
#include"util/debug_log.c" #include"util/debug_log.c"
#include"util/memory.c" #include"util/memory.c"
#include"util/strings.c" #include"util/strings.c"
#include"util/utf8.c" #include"util/utf8.c"
#include"util/hash.c" #include"util/hash.c"
#include"util/ringbuffer.c" #include"util/ringbuffer.c"
//--------------------------------------------------------------- //---------------------------------------------------------------
// platform implementations // platform implementations
//--------------------------------------------------------------- //---------------------------------------------------------------
#include"platform.h" #include"platform.h"
#if defined(OS_WIN64) #if defined(OS_WIN64)
#include"platform/win32_base_allocator.c" #include"platform/win32_base_allocator.c"
//TODO //TODO
#elif defined(OS_MACOS) #elif defined(OS_MACOS)
#include"platform/unix_base_allocator.c" #include"platform/unix_base_allocator.c"
#include"platform/osx_clock.c" #include"platform/osx_clock.c"
/* /*
#include"platform/unix_rng.c" #include"platform/unix_rng.c"
#include"platform/posix_thread.c" #include"platform/posix_thread.c"
#include"platform/posix_socket.c" #include"platform/posix_socket.c"
*/ */
#elif defined(OS_LINUX) #elif defined(OS_LINUX)
#include"platform/unix_base_allocator.c" #include"platform/unix_base_allocator.c"
#include"platform/linux_clock.c" #include"platform/linux_clock.c"
/* /*
#include"platform/unix_rng.c" #include"platform/unix_rng.c"
#include"platform/posix_thread.c" #include"platform/posix_thread.c"
#include"platform/posix_socket.c" #include"platform/posix_socket.c"
*/ */
#else #else
#error "Unsupported platform" #error "Unsupported platform"
#endif #endif
//--------------------------------------------------------------- //---------------------------------------------------------------
// application layer // application layer
//--------------------------------------------------------------- //---------------------------------------------------------------
#if defined(OS_WIN64) #if defined(OS_WIN64)
#include"win32_app.c" #include"win32_app.c"
#include"win32_gl_surface.c" // #include"win32_gl_surface.c"
#elif defined(OS_MACOS) #include"win32_gles_surface.c"
//NOTE: macos application layer is defined in milepost.m #elif defined(OS_MACOS)
#else //NOTE: macos application layer is defined in milepost.m
#error "Unsupported platform" #else
#endif #error "Unsupported platform"
#endif
//---------------------------------------------------------------
// graphics/ui layer //---------------------------------------------------------------
//--------------------------------------------------------------- // graphics/ui layer
#include"graphics.c" //---------------------------------------------------------------
//#include"ui.c" #include"graphics.c"
//#include"ui.c"

View File

@ -1,51 +1,51 @@
/************************************************************//** /************************************************************//**
* *
* @file: milepost.h * @file: milepost.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 13/02/2021 * @date: 13/02/2021
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#ifndef __MILEPOST_H_ #ifndef __MILEPOST_H_
#define __MILEPOST_H_ #define __MILEPOST_H_
//---------------------------------------------------------------- //----------------------------------------------------------------
// utility layer // utility layer
//---------------------------------------------------------------- //----------------------------------------------------------------
#include"platform.h" #include"platform.h"
#include"typedefs.h" #include"typedefs.h"
#include"macro_helpers.h" #include"macro_helpers.h"
#include"debug_log.h" #include"debug_log.h"
#include"lists.h" #include"lists.h"
#include"memory.h" #include"memory.h"
#include"strings.h" #include"strings.h"
#include"utf8.h" #include"utf8.h"
#include"hash.h" #include"hash.h"
//---------------------------------------------------------------- //----------------------------------------------------------------
// platform layer // platform layer
//---------------------------------------------------------------- //----------------------------------------------------------------
#include"platform_clock.h" #include"platform_clock.h"
/* /*
#include"platform_rng.h" #include"platform_rng.h"
#include"platform_socket.h" #include"platform_socket.h"
#include"platform_thread.h" #include"platform_thread.h"
*/ */
//---------------------------------------------------------------- //----------------------------------------------------------------
// application layer // application layer
//---------------------------------------------------------------- //----------------------------------------------------------------
#include"mp_app.h" #include"mp_app.h"
#if defined(OS_WIN64) || defined(OS_WIN32) #if defined(OS_WIN64) || defined(OS_WIN32)
#define WIN32_GL_LOADER_API #define WIN32_GL_LOADER_API
#include"win32_gl_loader.h" // #include"win32_gl_loader.h"
#endif #endif
//---------------------------------------------------------------- //----------------------------------------------------------------
// graphics/ui layer // graphics/ui layer
//---------------------------------------------------------------- //----------------------------------------------------------------
#include"graphics.h" #include"graphics.h"
//#include"ui.h" //#include"ui.h"
#endif //__MILEPOST_H_ #endif //__MILEPOST_H_

View File

@ -1,220 +1,220 @@
/************************************************************//** /************************************************************//**
* *
* @file: win32_gl_surface.c * @file: win32_gl_surface.c
* @author: Martin Fouilleul * @author: Martin Fouilleul
* @date: 01/08/2022 * @date: 01/08/2022
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#define WIN32_GL_LOADER_IMPL #define WIN32_GL_LOADER_IMPL
#include"win32_gl_loader.h" #include"win32_gl_loader.h"
#include"graphics_internal.h" #include"graphics_internal.h"
#include"win32_app.h" #include"win32_app.h"
#define MG_IMPLEMENTS_BACKEND_GL #define MG_IMPLEMENTS_BACKEND_GL
typedef struct mg_gl_surface typedef struct mg_gl_surface
{ {
mg_surface_info interface; mg_surface_data interface;
HDC hDC; HDC hDC;
HGLRC glContext; HGLRC glContext;
} mg_gl_surface; } mg_gl_surface;
void mg_gl_surface_destroy(mg_surface_info* interface) void mg_gl_surface_destroy(mg_surface_data* interface)
{ {
mg_gl_surface* surface = (mg_gl_surface*)interface; mg_gl_surface* surface = (mg_gl_surface*)interface;
//TODO //TODO
} }
void mg_gl_surface_prepare(mg_surface_info* interface) void mg_gl_surface_prepare(mg_surface_data* interface)
{ {
mg_gl_surface* surface = (mg_gl_surface*)interface; mg_gl_surface* surface = (mg_gl_surface*)interface;
wglMakeCurrent(surface->hDC, surface->glContext); wglMakeCurrent(surface->hDC, surface->glContext);
} }
void mg_gl_surface_present(mg_surface_info* interface) void mg_gl_surface_present(mg_surface_data* interface)
{ {
mg_gl_surface* surface = (mg_gl_surface*)interface; mg_gl_surface* surface = (mg_gl_surface*)interface;
SwapBuffers(surface->hDC); SwapBuffers(surface->hDC);
} }
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB; PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
PFNGLCREATESHADERPROC glCreateShader; PFNGLCREATESHADERPROC glCreateShader;
PFNGLCREATEPROGRAMPROC glCreateProgram; PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLATTACHSHADERPROC glAttachShader; PFNGLATTACHSHADERPROC glAttachShader;
PFNGLCOMPILESHADERPROC glCompileShader; PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLGETSHADERIVPROC glGetShaderiv; PFNGLGETSHADERIVPROC glGetShaderiv;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
PFNGLSHADERSOURCEPROC glShaderSource; PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLLINKPROGRAMPROC glLinkProgram; PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLGETPROGRAMIVPROC glGetProgramiv; PFNGLGETPROGRAMIVPROC glGetProgramiv;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLUSEPROGRAMPROC glUseProgram; PFNGLUSEPROGRAMPROC glUseProgram;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray; PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
PFNGLGENBUFFERSPROC glGenBuffers; PFNGLGENBUFFERSPROC glGenBuffers;
PFNGLBINDBUFFERPROC glBindBuffer; PFNGLBINDBUFFERPROC glBindBuffer;
PFNGLBUFFERDATAPROC glBufferData; PFNGLBUFFERDATAPROC glBufferData;
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv; PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
mg_surface mg_gl_surface_create_for_window(mp_window window) mg_surface mg_gl_surface_create_for_window(mp_window window)
{ {
mg_surface surfaceHandle = mg_surface_nil(); mg_surface surfaceHandle = mg_surface_nil();
mp_window_data* windowData = mp_window_ptr_from_handle(window); mp_window_data* windowData = mp_window_ptr_from_handle(window);
if(windowData) if(windowData)
{ {
//NOTE: create a dummy window //NOTE: create a dummy window
WNDCLASS windowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, WNDCLASS windowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
.lpfnWndProc = WinProc, .lpfnWndProc = WinProc,
.hInstance = GetModuleHandleW(NULL), .hInstance = GetModuleHandleW(NULL),
.lpszClassName = "HelperWindowClass", .lpszClassName = "HelperWindowClass",
.hCursor = LoadCursor(0, IDC_ARROW)}; .hCursor = LoadCursor(0, IDC_ARROW)};
if(!RegisterClass(&windowClass)) if(!RegisterClass(&windowClass))
{ {
//TODO: error //TODO: error
goto quit; goto quit;
} }
HWND helperWindowHandle = CreateWindow("HelperWindowClass", "Test Window", HWND helperWindowHandle = CreateWindow("HelperWindowClass", "Test Window",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
800, 600, 800, 600,
0, 0, windowClass.hInstance, 0); 0, 0, windowClass.hInstance, 0);
if(!helperWindowHandle) if(!helperWindowHandle)
{ {
//TODO: error //TODO: error
goto quit; goto quit;
} }
//NOTE(martin): create a dummy OpenGL context, to be able to load extensions //NOTE(martin): create a dummy OpenGL context, to be able to load extensions
HDC dummyDC = GetDC(helperWindowHandle); HDC dummyDC = GetDC(helperWindowHandle);
PIXELFORMATDESCRIPTOR pixelFormatDesc = PIXELFORMATDESCRIPTOR pixelFormatDesc =
{ {
sizeof(PIXELFORMATDESCRIPTOR), sizeof(PIXELFORMATDESCRIPTOR),
1, 1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
32, // Colordepth of the framebuffer. 32, // Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
0, 0,
0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
24, // Number of bits for the depthbuffer 24, // Number of bits for the depthbuffer
8, // Number of bits for the stencilbuffer 8, // Number of bits for the stencilbuffer
0, // Number of Aux buffers in the framebuffer. 0, // Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE, PFD_MAIN_PLANE,
0, 0,
0, 0, 0 0, 0, 0
}; };
int pixelFormat = ChoosePixelFormat(dummyDC, &pixelFormatDesc); int pixelFormat = ChoosePixelFormat(dummyDC, &pixelFormatDesc);
SetPixelFormat(dummyDC, pixelFormat, &pixelFormatDesc); SetPixelFormat(dummyDC, pixelFormat, &pixelFormatDesc);
HGLRC dummyGLContext = wglCreateContext(dummyDC); HGLRC dummyGLContext = wglCreateContext(dummyDC);
wglMakeCurrent(dummyDC, dummyGLContext); wglMakeCurrent(dummyDC, dummyGLContext);
//NOTE(martin): now load extension functions //NOTE(martin): now load extension functions
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)wglGetProcAddress("wglMakeContextCurrentARB"); wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)wglGetProcAddress("wglMakeContextCurrentARB");
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader"); glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
glCreateProgram = (PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram"); glCreateProgram = (PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
glAttachShader = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader"); glAttachShader = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource"); glShaderSource = (PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader"); glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
glGetShaderiv = (PFNGLGETSHADERIVPROC)wglGetProcAddress("glGetShaderiv"); glGetShaderiv = (PFNGLGETSHADERIVPROC)wglGetProcAddress("glGetShaderiv");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog"); glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog");
glLinkProgram = (PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram"); glLinkProgram = (PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram");
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)wglGetProcAddress("glGetProgramiv"); glGetProgramiv = (PFNGLGETPROGRAMIVPROC)wglGetProcAddress("glGetProgramiv");
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)wglGetProcAddress("glGetProgramInfoLog"); glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)wglGetProcAddress("glGetProgramInfoLog");
glUseProgram = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram"); glUseProgram = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress("glGenVertexArrays"); glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress("glBindVertexArray"); glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress("glBindVertexArray");
glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers"); glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers");
glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer"); glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData"); glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)wglGetProcAddress("glUniformMatrix4fv"); glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)wglGetProcAddress("glUniformMatrix4fv");
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer"); glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer");
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray"); glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray");
//NOTE(martin): now create the true pixel format and gl context //NOTE(martin): now create the true pixel format and gl context
int pixelFormatAttrs[] = { int pixelFormatAttrs[] = {
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32, WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24, WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8, WGL_STENCIL_BITS_ARB, 8,
0}; 0};
HDC hDC = GetDC(windowData->win32.hWnd); HDC hDC = GetDC(windowData->win32.hWnd);
u32 numFormats = 0; u32 numFormats = 0;
wglChoosePixelFormatARB(hDC, pixelFormatAttrs, 0, 1, &pixelFormat, &numFormats); wglChoosePixelFormatARB(hDC, pixelFormatAttrs, 0, 1, &pixelFormat, &numFormats);
if(!pixelFormat) if(!pixelFormat)
{ {
//TODO: error //TODO: error
} }
SetPixelFormat(hDC, pixelFormat, &pixelFormatDesc); SetPixelFormat(hDC, pixelFormat, &pixelFormatDesc);
int contextAttrs[] = { int contextAttrs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 4, WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 3,
0}; 0};
HGLRC glContext = wglCreateContextAttribsARB(hDC, dummyGLContext, contextAttrs); HGLRC glContext = wglCreateContextAttribsARB(hDC, dummyGLContext, contextAttrs);
if(!glContext) if(!glContext)
{ {
//TODO error //TODO error
int error = GetLastError(); int error = GetLastError();
printf("error: %i\n", error); printf("error: %i\n", error);
} }
//NOTE: destroy dummy context and dummy window //NOTE: destroy dummy context and dummy window
wglMakeCurrent(hDC, 0); wglMakeCurrent(hDC, 0);
wglDeleteContext(dummyGLContext); wglDeleteContext(dummyGLContext);
DestroyWindow(helperWindowHandle); DestroyWindow(helperWindowHandle);
//NOTE: make gl context current //NOTE: make gl context current
wglMakeCurrent(hDC, glContext); wglMakeCurrent(hDC, glContext);
wglSwapIntervalEXT(1); wglSwapIntervalEXT(1);
//TODO save important info in surface_data and return a handle //TODO save important info in surface_data and return a handle
mg_gl_surface* surface = malloc_type(mg_gl_surface); mg_gl_surface* surface = malloc_type(mg_gl_surface);
surface->interface.backend = MG_BACKEND_GL; surface->interface.backend = MG_BACKEND_GL;
surface->interface.destroy = mg_gl_surface_destroy; surface->interface.destroy = mg_gl_surface_destroy;
surface->interface.prepare = mg_gl_surface_prepare; surface->interface.prepare = mg_gl_surface_prepare;
surface->interface.present = mg_gl_surface_present; surface->interface.present = mg_gl_surface_present;
//TODO: get/set frame/hidden //TODO: get/set frame/hidden
surface->hDC = hDC; surface->hDC = hDC;
surface->glContext = glContext; surface->glContext = glContext;
surfaceHandle = mg_surface_alloc_handle((mg_surface_info*)surface); surfaceHandle = mg_surface_alloc_handle((mg_surface_data*)surface);
} }
quit:; quit:;
return(surfaceHandle); return(surfaceHandle);
} }

14
src/win32_gl_surface.h Normal file
View File

@ -0,0 +1,14 @@
/************************************************************//**
*
* @file: win32_gl_surface.c
* @author: Martin Fouilleul
* @date: 28/01/2023
* @revision:
*
*****************************************************************/
#ifndef __WIN32_GL_SURFACE_H_
#define __WIN32_GL_SURFACE_H_
mg_surface mg_gl_surface_create_for_window(mp_window window);
#endif // __WIN32_GL_SURFACE_H_

125
src/win32_gles_surface.c Normal file
View File

@ -0,0 +1,125 @@
/************************************************************//**
*
* @file: osx_gles_surface.cpp
* @author: Martin Fouilleul
* @date: 18/08/2022
* @revision:
*
*****************************************************************/
#include<GLES3/gl32.h>
#define EGL_EGLEXT_PROTOTYPES
#include<EGL/egl.h>
#include<EGL/eglext.h>
#include"graphics_internal.h"
typedef struct mg_gles_surface
{
mg_surface_data interface;
HWND hWnd;
EGLDisplay eglDisplay;
EGLConfig eglConfig;
EGLContext eglContext;
EGLSurface eglSurface;
} mg_gles_surface;
void mg_gles_surface_destroy(mg_surface_data* interface)
{
//////////////////////////////////////////////////
//TODO
//////////////////////////////////////////////////
}
void mg_gles_surface_prepare(mg_surface_data* interface)
{
mg_gles_surface* surface = (mg_gles_surface*)interface;
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
}
void mg_gles_surface_present(mg_surface_data* interface)
{
//TODO: eglSwapBuffers seem to never block in macOS (ie eglSwapInterval doesn't seem to have any effect)
// We need to use a CVDisplayLink to time this if we want surface present to block
mg_gles_surface* surface = (mg_gles_surface*)interface;
eglSwapBuffers(surface->eglDisplay, surface->eglSurface);
}
/*
void mg_gles_surface_set_frame(mg_surface_data* interface, mp_rect frame);
mp_rect mg_gles_surface_get_frame(mg_surface_data* interface);
void mg_gles_surface_set_hidden(mg_surface_data* interface, bool hidden);
bool mg_gles_surface_get_hidden(mg_surface_data* interface);
*/
mg_surface mg_gles_surface_create_for_window(mp_window window)
{
mg_surface res = mg_surface_nil();
mp_window_data* windowData = mp_window_ptr_from_handle(window);
if(windowData)
{
mg_gles_surface* surface = malloc_type(mg_gles_surface);
memset(surface, 0, sizeof(mg_gles_surface));
surface->interface.backend = MG_BACKEND_GLES;
surface->interface.destroy = mg_gles_surface_destroy;
surface->interface.prepare = mg_gles_surface_prepare;
surface->interface.present = mg_gles_surface_present;
/*TODO
surface->interface.getFrame = mg_gles_surface_get_frame;
surface->interface.setFrame = mg_gles_surface_set_frame;
surface->interface.getHidden = mg_gles_surface_get_hidden;
surface->interface.setHidden = mg_gles_surface_set_hidden;
*/
surface->hWnd = windowData->win32.hWnd;
EGLAttrib displayAttribs[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE,
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
EGL_NONE};
surface->eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, (void*)EGL_DEFAULT_DISPLAY, displayAttribs);
eglInitialize(surface->eglDisplay, NULL, NULL);
EGLint const configAttributes[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_STENCIL_SIZE, 8,
EGL_SAMPLE_BUFFERS, 0,
EGL_SAMPLES, EGL_DONT_CARE,
EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
EGL_NONE };
int numConfigs = 0;
eglChooseConfig(surface->eglDisplay, configAttributes, &surface->eglConfig, 1, &numConfigs);
EGLint const surfaceAttributes[] = {EGL_NONE};
surface->eglSurface = eglCreateWindowSurface(surface->eglDisplay, surface->eglConfig, surface->hWnd, surfaceAttributes);
eglBindAPI(EGL_OPENGL_ES_API);
EGLint contextAttributes[] = {
EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
EGL_CONTEXT_MINOR_VERSION_KHR, 0, //NOTE: Angle can't create a GLES 3.1 context on macOS
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE,
EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE,
EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_FALSE,
EGL_NONE};
surface->eglContext = eglCreateContext(surface->eglDisplay, surface->eglConfig, EGL_NO_CONTEXT, contextAttributes);
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
eglSwapInterval(surface->eglDisplay, 1);
res = mg_surface_alloc_handle((mg_surface_data*)surface);
}
return(res);
}

14
src/win32_gles_surface.h Normal file
View File

@ -0,0 +1,14 @@
/************************************************************//**
*
* @file: win32_gles_surface.h
* @author: Martin Fouilleul
* @date: 28/01/2023
* @revision:
*
*****************************************************************/
#ifndef __WIN32_GLES_SURFACE_H_
#define __WIN32_GLES_SURFACE_H_
mg_surface mg_gles_surface_create_for_window(mg_window window);
#endif // __WIN32_GLES_SURFACE_H_