3 Commits

Author SHA1 Message Date
91d50e2938 [rcore][win32] Fix WGL pixel format not being applied (#6219)
* [rcore][win32] Fix WGL pixel format not being applied

* Specify Stencil Bits In Fallback Pixel Format
2026-10-06 08:22:59 +02:00
92f1f3d5d5 [rcore][web] Avoid glfwGetProcAddress() to reduce code size (#6220)
* [rcore][web] Avoid glfwGetProcAddress() to reduce code size

* [build][cmake] Remove unneeded GL_ENABLE_GET_PROC_ADDRESS flag
2026-10-06 08:20:40 +02:00
Ray
f0736f6fb5 GLFW: Boundaries check #6222 2026-10-06 07:49:07 +02:00
5 changed files with 91 additions and 15 deletions

View File

@ -30,7 +30,7 @@ target_link_libraries(${PROJECT_NAME} raylib)
# Web Configurations # Web Configurations
if (${PLATFORM} STREQUAL "Web") if (${PLATFORM} STREQUAL "Web")
set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html") # Tell Emscripten to build an example.html file. set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html") # Tell Emscripten to build an example.html file.
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY -s GL_ENABLE_GET_PROC_ADDRESS=1") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY")
endif() endif()
# Checks if OSX and links appropriate frameworks (Only required on MacOS) # Checks if OSX and links appropriate frameworks (Only required on MacOS)

View File

@ -2093,7 +2093,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
// GLFW3: Keyboard callback, runs on key pressed // GLFW3: Keyboard callback, runs on key pressed
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
{ {
if (key < 0) return; // Security check, macOS fn key generates -1 if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return; // Security check, macOS fn key generates -1
// WARNING: GLFW could return GLFW_REPEAT, it needs to be considered as 1 // WARNING: GLFW could return GLFW_REPEAT, it needs to be considered as 1
// to work properly with our implementation (IsKeyDown/IsKeyUp checks) // to work properly with our implementation (IsKeyDown/IsKeyUp checks)

View File

@ -1401,7 +1401,23 @@ void PollInputEvents(void)
// NOTE: Creating a dummy context first to query required extensions // NOTE: Creating a dummy context first to query required extensions
HGLRC InitOpenGL(HWND hwnd, HDC hdc) HGLRC InitOpenGL(HWND hwnd, HDC hdc)
{ {
// First, create a dummy context to get WGL extensions // Create an invisible window for initial dummy OpenGL context
WNDCLASSEXW dummyWindowClass = {
.cbSize = sizeof(WNDCLASSEXW),
.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
.lpfnWndProc = DefWindowProcW,
.hInstance = GetModuleHandleW(NULL),
.lpszClassName = L"wglDummy"
};
RegisterClassExW(&dummyWindowClass);
HWND dummyWindow = CreateWindowExW(
0, dummyWindowClass.lpszClassName, L"dummyWindow",
0, 0, 0, 1, 1, NULL, NULL, NULL, NULL);
HDC dummyHDC = GetDC(dummyWindow);
// Create a dummy OpenGL context to get WGL extensions
PIXELFORMATDESCRIPTOR pixelFormatDesc = { PIXELFORMATDESCRIPTOR pixelFormatDesc = {
.nSize = sizeof(PIXELFORMATDESCRIPTOR), .nSize = sizeof(PIXELFORMATDESCRIPTOR),
.nVersion = 1, .nVersion = 1,
@ -1410,18 +1426,19 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc)
.cColorBits = 32, .cColorBits = 32,
.cAlphaBits = 8, .cAlphaBits = 8,
.cDepthBits = 24, .cDepthBits = 24,
.cStencilBits = 8,
.iLayerType = PFD_MAIN_PLANE .iLayerType = PFD_MAIN_PLANE
}; };
int pixelFormat = ChoosePixelFormat(hdc, &pixelFormatDesc); int dummyPixelFormat = ChoosePixelFormat(dummyHDC, &pixelFormatDesc);
SetPixelFormat(hdc, pixelFormat, &pixelFormatDesc); SetPixelFormat(dummyHDC, dummyPixelFormat, &pixelFormatDesc);
//int pixelFormat = ChoosePixelFormat(platform.hdc, &pixelFormatDesc); //int pixelFormat = ChoosePixelFormat(platform.hdc, &pixelFormatDesc);
//if (!pixelFormat) { TRACELOG(LOG_ERROR, "%s failed, error=%lu", "ChoosePixelFormat", GetLastError()); return -1; } //if (!pixelFormat) { TRACELOG(LOG_ERROR, "%s failed, error=%lu", "ChoosePixelFormat", GetLastError()); return -1; }
//if (!SetPixelFormat(platform.hdc, pixelFormat, &pixelFormatDesc)) { TRACELOG(LOG_ERROR, "%s failed, error=%lu", "SetPixelFormat", GetLastError()); return -1; } //if (!SetPixelFormat(platform.hdc, pixelFormat, &pixelFormatDesc)) { TRACELOG(LOG_ERROR, "%s failed, error=%lu", "SetPixelFormat", GetLastError()); return -1; }
HGLRC tempContext = wglCreateContext(hdc); HGLRC tempContext = wglCreateContext(dummyHDC);
//if (!tempContext) { TRACELOG(LOG_ERROR, "%s failed, error=%lu", "wglCreateContext", GetLastError()); return -1; } //if (!tempContext) { TRACELOG(LOG_ERROR, "%s failed, error=%lu", "wglCreateContext", GetLastError()); return -1; }
BOOL result = wglMakeCurrent(hdc, tempContext); BOOL result = wglMakeCurrent(dummyHDC, tempContext);
//if (!result) { TRACELOG(LOG_ERROR, "%s failed, error=%lu", "wglMakeCurrent", GetLastError()); return -1; } //if (!result) { TRACELOG(LOG_ERROR, "%s failed, error=%lu", "wglMakeCurrent", GetLastError()); return -1; }
// Load WGL extension entry points // Load WGL extension entry points
@ -1431,6 +1448,7 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc)
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
// Setup modern pixel format if extension is available // Setup modern pixel format if extension is available
bool selectedModernPixelFormat = false;
if (wglChoosePixelFormatARB) if (wglChoosePixelFormatARB)
{ {
int pixelFormatAttribs[] = { int pixelFormatAttribs[] = {
@ -1440,10 +1458,10 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc)
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_RED_BITS_ARB, 8, WGL_RED_BITS_ARB, 8,
//WGL_GREEN_BITS_ARB, 8, WGL_GREEN_BITS_ARB, 8,
//WGL_BLUE_BITS_ARB, 8, WGL_BLUE_BITS_ARB, 8,
//WGL_ALPHA_BITS_ARB, 8, WGL_ALPHA_BITS_ARB, 8,
WGL_DEPTH_BITS_ARB, 24, WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8, WGL_STENCIL_BITS_ARB, 8,
0 // Terminator 0 // Terminator
@ -1455,10 +1473,18 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc)
{ {
PIXELFORMATDESCRIPTOR newPixelFormatDescriptor = { 0 }; PIXELFORMATDESCRIPTOR newPixelFormatDescriptor = { 0 };
DescribePixelFormat(hdc, format, sizeof(newPixelFormatDescriptor), &newPixelFormatDescriptor); DescribePixelFormat(hdc, format, sizeof(newPixelFormatDescriptor), &newPixelFormatDescriptor);
SetPixelFormat(hdc, format, &newPixelFormatDescriptor); BOOL success = SetPixelFormat(hdc, format, &newPixelFormatDescriptor);
selectedModernPixelFormat = (success == TRUE);
} }
} }
if (!selectedModernPixelFormat)
{
// If modern pixel format selection failed, fall back to old SetPixelFormat
int pixelFormat = ChoosePixelFormat(hdc, &pixelFormatDesc);
SetPixelFormat(hdc, pixelFormat, &pixelFormatDesc);
}
// Create real modern OpenGL context (3.3 core) // Create real modern OpenGL context (3.3 core)
HGLRC realContext = NULL; HGLRC realContext = NULL;
if (wglCreateContextAttribsARB) if (wglCreateContextAttribsARB)
@ -1521,10 +1547,18 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc)
// ERROR_INVALID_PROFILE_ARB (0x2096) // ERROR_INVALID_PROFILE_ARB (0x2096)
if (realContext == NULL) TRACELOG(LOG_ERROR, "GL: Error creating requested context: %lu", GetLastError()); if (realContext == NULL) TRACELOG(LOG_ERROR, "GL: Error creating requested context: %lu", GetLastError());
} }
else
{
// If modern context extension isn't available, fall back to classic context creation
realContext = wglCreateContext(hdc);
}
// Cleanup dummy temp context // Cleanup dummy temp context and window
wglMakeCurrent(NULL, NULL); wglMakeCurrent(NULL, NULL);
wglDeleteContext(tempContext); wglDeleteContext(tempContext);
ReleaseDC(dummyWindow, dummyHDC);
DestroyWindow(dummyWindow);
UnregisterClassW(dummyWindowClass.lpszClassName, dummyWindowClass.hInstance);
// Activate real context // Activate real context
if (realContext) wglMakeCurrent(hdc, realContext); if (realContext) wglMakeCurrent(hdc, realContext);

View File

@ -111,6 +111,9 @@ static const char cursorLUT[11][12] = {
int InitPlatform(void); // Initialize platform (graphics, inputs and more) int InitPlatform(void); // Initialize platform (graphics, inputs and more)
void ClosePlatform(void); // Close platform void ClosePlatform(void); // Close platform
// OpenGL extensions loader
static void *WebGLGetProcAddress(const char *procName); // Get WebGL extension procedure address, used by rlLoadExtensions()
// Error callback event // Error callback event
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
@ -1442,7 +1445,7 @@ int InitPlatform(void)
// Load OpenGL extensions // Load OpenGL extensions
// NOTE: GL procedures address loader is required to load extensions // NOTE: GL procedures address loader is required to load extensions
rlLoadExtensions(glfwGetProcAddress); rlLoadExtensions(WebGLGetProcAddress);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Initialize events callbacks // Initialize events callbacks
@ -1499,6 +1502,24 @@ void ClosePlatform(void)
glfwTerminate(); glfwTerminate();
} }
// Get WebGL extension procedure address
// WARNING: rlGetProcAddress() uses this loader, so it only returns the functions listed below
static void *WebGLGetProcAddress(const char *procName)
{
void *proc = NULL;
#if defined(GRAPHICS_API_OPENGL_ES2)
if (strcmp(procName, "glGenVertexArraysOES") == 0) proc = (void *)glGenVertexArraysOES;
else if (strcmp(procName, "glBindVertexArrayOES") == 0) proc = (void *)glBindVertexArrayOES;
else if (strcmp(procName, "glDeleteVertexArraysOES") == 0) proc = (void *)glDeleteVertexArraysOES;
else if (strcmp(procName, "glDrawArraysInstancedANGLE") == 0) proc = (void *)glDrawArraysInstancedANGLE;
else if (strcmp(procName, "glDrawElementsInstancedANGLE") == 0) proc = (void *)glDrawElementsInstancedANGLE;
else if (strcmp(procName, "glVertexAttribDivisorANGLE") == 0) proc = (void *)glVertexAttribDivisorANGLE;
#endif
return proc;
}
// GLFW3 callback functions, called on GLFW registered events // GLFW3 callback functions, called on GLFW registered events
//------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------
// GLFW3: Called on errors // GLFW3: Called on errors

View File

@ -209,6 +209,9 @@ static const char cursorLUT[11][12] = {
int InitPlatform(void); // Initialize platform (graphics, inputs and more) int InitPlatform(void); // Initialize platform (graphics, inputs and more)
void ClosePlatform(void); // Close platform void ClosePlatform(void); // Close platform
// OpenGL extensions loader
static void *WebGLGetProcAddress(const char *procName); // Get WebGL extension procedure address, used by rlLoadExtensions()
// Emscripten window callback events // Emscripten window callback events
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData); static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *event, void *userData);
static EM_BOOL EmscriptenFocusCallback(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData); static EM_BOOL EmscriptenFocusCallback(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData);
@ -1387,7 +1390,7 @@ int InitPlatform(void)
// Load OpenGL extensions // Load OpenGL extensions
// NOTE: GL procedures address loader is required to load extensions // NOTE: GL procedures address loader is required to load extensions
if (platform.glContext != 0) rlLoadExtensions(emscripten_webgl_get_proc_address); if (platform.glContext != 0) rlLoadExtensions(WebGLGetProcAddress);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Initialize events callbacks // Initialize events callbacks
@ -1450,6 +1453,24 @@ void ClosePlatform(void)
if (platform.glContext != 0) emscripten_webgl_destroy_context(platform.glContext); if (platform.glContext != 0) emscripten_webgl_destroy_context(platform.glContext);
} }
// Get WebGL extension procedure address
// WARNING: rlGetProcAddress() uses this loader, so it only returns the functions listed below
static void *WebGLGetProcAddress(const char *procName)
{
void *proc = NULL;
#if defined(GRAPHICS_API_OPENGL_ES2)
if (strcmp(procName, "glGenVertexArraysOES") == 0) proc = (void *)glGenVertexArraysOES;
else if (strcmp(procName, "glBindVertexArrayOES") == 0) proc = (void *)glBindVertexArrayOES;
else if (strcmp(procName, "glDeleteVertexArraysOES") == 0) proc = (void *)glDeleteVertexArraysOES;
else if (strcmp(procName, "glDrawArraysInstancedANGLE") == 0) proc = (void *)glDrawArraysInstancedANGLE;
else if (strcmp(procName, "glDrawElementsInstancedANGLE") == 0) proc = (void *)glDrawElementsInstancedANGLE;
else if (strcmp(procName, "glVertexAttribDivisorANGLE") == 0) proc = (void *)glVertexAttribDivisorANGLE;
#endif
return proc;
}
// Emscripten callback functions, called on specific browser events // Emscripten callback functions, called on specific browser events
//------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------
// Emscripten: Called on resize event // Emscripten: Called on resize event