diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c4c74ade..4c94de63 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -287,6 +287,7 @@ video tutorials. - Ryogo Yoshimura - Lukas Zanner - Andrey Zholos + - Tianlan Zhou - Aihui Zhu - Santi Zupancic - Jonas Ã…dahl diff --git a/README.md b/README.md index 6a9b3bfe..bcaa9c37 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,7 @@ information on what to include when reporting a bug. (#442) - [EGL] Added ANGLE backend selection via `EGL_ANGLE_platform_angle` extension (#1380) + - Added `GLFW_ACCELERATION` window hint for hardware acceleration (#2491) ## Changelog since 3.3 diff --git a/docs/news.md b/docs/news.md index e68464f6..b352d23e 100644 --- a/docs/news.md +++ b/docs/news.md @@ -141,6 +141,16 @@ contexts. [ANGLE]: https://chromium.googlesource.com/angle/angle/ +#### Window hint for hardware acceleration {#acceleration_34} + +You can use window hint [GLFW_ACCELERATION](@ref GLFW_ACCELERATION_hint) to +specify whether hardware acceleration is preferred or not. The default value +is to prefer hardware acceleration. You can get whether hardware acceleration +is enabled with the window attribute +[GLFW_ACCELERATION](@ref GLFW_ACCELERATION_attrib). This feature is only +available on WGL currently. + + ### Caveats for version 3.4 {#caveats} #### Multiple sets of native access functions {#native_34} @@ -227,6 +237,13 @@ Events posted with @ref glfwPostEmptyEvent now use a separate unnamed pipe instead of sending an X11 client event to the helper window. +#### Microsoft GDI software OpenGL ICD support {#gdi_opengl_icd_34} + +GLFW now supports creating window when the Microsoft GDI software OpenGL ICD is +the only available implementation. +See [GLFW_ACCELERATION](@ref GLFW_ACCELERATION_hint) for more details. + + ### Deprecations in version 3.4 {#deprecations_34} ### Removals in 3.4 {#removals_34} @@ -323,6 +340,7 @@ then GLFW will fail to initialize. - @ref GLFW_WAYLAND_PREFER_LIBDECOR - @ref GLFW_WAYLAND_DISABLE_LIBDECOR - @ref GLFW_SCALE_FRAMEBUFFER + - @ref GLFW_ACCELERATION ## Release notes for earlier versions {#news_archive} diff --git a/docs/window.md b/docs/window.md index 371baa56..45601a67 100644 --- a/docs/window.md +++ b/docs/window.md @@ -336,6 +336,15 @@ __GLFW_DOUBLEBUFFER__ specifies whether the framebuffer should be double buffered. You nearly always want to use double buffering. This is a hard constraint. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. +@anchor GLFW_ACCELERATION +@anchor GLFW_ACCELERATION_hint +__GLFW_ACCELERATION__ specifies whether the hardware acceleration should be +preferred. By default, hardware acceleration is preferred, and will fallback +to no acceleration if hardware acceleration is unavailable. Possible values +are `GLFW_TRUE` and `GLFW_FALSE`. + +This hint only has an effect on WGL. + #### Monitor related hints {#window_hints_mtr} @@ -1487,6 +1496,11 @@ __GLFW_DOUBLEBUFFER__ indicates whether the specified window is double-buffered when rendering with OpenGL or OpenGL ES. This can be set before creation with the [GLFW_DOUBLEBUFFER](@ref GLFW_DOUBLEBUFFER_hint) window hint. +@anchor GLFW_ACCELERATION_attrib +__GLFW_ACCELERATION__ indicates whether the specified window is hardware +accelerated when rendering with OpenGL or OpenGL ES. This can be set before +creation with the [GLFW_ACCELERATION](@ref GLFW_ACCELERATION_hint) window hint. + ## Buffer swapping {#buffer_swap} diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 9c55ac9d..f1dc891c 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1022,6 +1022,14 @@ extern "C" { * [attribute](@ref GLFW_DOUBLEBUFFER_attrib). */ #define GLFW_DOUBLEBUFFER 0x00021010 +/*! @brief Hardware acceleration hint. + * + * Hardware acceleration [hint](@ref GLFW_ACCELERATION_hint) and + * [attribute](@ref GLFW_ACCELERATION_attrib). + * + * @since Added in version 3.4. + */ +#define GLFW_ACCELERATION 0x00021011 /*! @brief Context client API hint and attribute. * @@ -3158,9 +3166,6 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value); * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE, @ref * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. * - * @remark @win32 Window creation will fail if the Microsoft GDI software - * OpenGL implementation is the only one available. - * * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it * will be set as the initial icon for the window. If no such icon is present, * the `IDI_APPLICATION` icon will be used instead. To set a different icon, diff --git a/src/context.c b/src/context.c index cc1fac4f..fc9e0c96 100644 --- a/src/context.c +++ b/src/context.c @@ -28,10 +28,10 @@ #include "internal.h" #include +#include +#include #include #include -#include -#include ////////////////////////////////////////////////////////////////////////// @@ -185,6 +185,7 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, unsigned int count) { unsigned int i; + bool accelerationMatch, closestAccelerationMatch = false; unsigned int missing, leastMissing = UINT_MAX; unsigned int colorDiff, leastColorDiff = UINT_MAX; unsigned int extraDiff, leastExtraDiff = UINT_MAX; @@ -201,6 +202,8 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, continue; } + accelerationMatch = desired->acceleration == current->acceleration; + // Count number of missing buffers { missing = 0; @@ -318,19 +321,25 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, // Least number of missing buffers is the most important heuristic, // then color buffer size match and lastly size match for other buffers - if (missing < leastMissing) + if (accelerationMatch && !closestAccelerationMatch) closest = current; - else if (missing == leastMissing) + else if (accelerationMatch == closestAccelerationMatch) { - if ((colorDiff < leastColorDiff) || - (colorDiff == leastColorDiff && extraDiff < leastExtraDiff)) - { + if (missing < leastMissing) closest = current; + else if (missing == leastMissing) + { + if ((colorDiff < leastColorDiff) || + (colorDiff == leastColorDiff && extraDiff < leastExtraDiff)) + { + closest = current; + } } } if (current == closest) { + closestAccelerationMatch = accelerationMatch; leastMissing = missing; leastColorDiff = colorDiff; leastExtraDiff = extraDiff; diff --git a/src/internal.h b/src/internal.h index 88733593..983feb5c 100644 --- a/src/internal.h +++ b/src/internal.h @@ -472,6 +472,7 @@ struct _GLFWfbconfig GLFWbool sRGB; GLFWbool doublebuffer; GLFWbool transparent; + GLFWbool acceleration; uintptr_t handle; }; @@ -532,6 +533,7 @@ struct _GLFWwindow GLFWbool shouldClose; void* userPointer; GLFWbool doublebuffer; + GLFWbool acceleration; GLFWvidmode videoMode; _GLFWmonitor* monitor; _GLFWcursor* cursor; diff --git a/src/wgl_context.c b/src/wgl_context.c index 8a23ffc4..a7e9cbf0 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -145,6 +145,8 @@ static int choosePixelFormatWGL(_GLFWwindow* window, { // Get pixel format attributes through "modern" extension + int acceleration; + if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc, pixelFormat, 0, attribCount, @@ -166,12 +168,11 @@ static int choosePixelFormatWGL(_GLFWwindow* window, if (FIND_ATTRIB_VALUE(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB) continue; - if (FIND_ATTRIB_VALUE(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB) - continue; - if (FIND_ATTRIB_VALUE(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer) continue; + acceleration = FIND_ATTRIB_VALUE(WGL_ACCELERATION_ARB); + u->redBits = FIND_ATTRIB_VALUE(WGL_RED_BITS_ARB); u->greenBits = FIND_ATTRIB_VALUE(WGL_GREEN_BITS_ARB); u->blueBits = FIND_ATTRIB_VALUE(WGL_BLUE_BITS_ARB); @@ -210,6 +211,10 @@ static int choosePixelFormatWGL(_GLFWwindow* window, u->sRGB = GLFW_TRUE; } } + + u->acceleration = + acceleration == WGL_GENERIC_ACCELERATION_ARB || + acceleration == WGL_FULL_ACCELERATION_ARB; } else { @@ -235,12 +240,6 @@ static int choosePixelFormatWGL(_GLFWwindow* window, continue; } - if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) && - (pfd.dwFlags & PFD_GENERIC_FORMAT)) - { - continue; - } - if (pfd.iPixelType != PFD_TYPE_RGBA) continue; @@ -264,6 +263,10 @@ static int choosePixelFormatWGL(_GLFWwindow* window, if (pfd.dwFlags & PFD_STEREO) u->stereo = GLFW_TRUE; + + u->acceleration = + (pfd.dwFlags & PFD_GENERIC_ACCELERATED) || + !(pfd.dwFlags & PFD_GENERIC_FORMAT); } u->handle = pixelFormat; @@ -437,8 +440,6 @@ GLFWbool _glfwInitWGL(void) // NOTE: A dummy context has to be created for opengl32.dll to load the // OpenGL ICD, from which we can then query WGL extensions - // NOTE: This code will accept the Microsoft GDI ICD; accelerated context - // creation failure occurs during manual pixel format enumeration dc = GetDC(_glfw.win32.helperWindowHandle); diff --git a/src/win32_platform.h b/src/win32_platform.h index 7e3d8845..96a41252 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -226,6 +226,8 @@ typedef enum #define WGL_TYPE_RGBA_ARB 0x202b #define WGL_ACCELERATION_ARB 0x2003 #define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 #define WGL_RED_BITS_ARB 0x2015 #define WGL_RED_SHIFT_ARB 0x2016 #define WGL_GREEN_BITS_ARB 0x2017 diff --git a/src/window.c b/src/window.c index 1463d169..31753297 100644 --- a/src/window.c +++ b/src/window.c @@ -235,6 +235,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->cursorMode = GLFW_CURSOR_NORMAL; window->doublebuffer = fbconfig.doublebuffer; + window->acceleration = fbconfig.acceleration; window->minwidth = GLFW_DONT_CARE; window->minheight = GLFW_DONT_CARE; @@ -287,6 +288,7 @@ void glfwDefaultWindowHints(void) _glfw.hints.framebuffer.depthBits = 24; _glfw.hints.framebuffer.stencilBits = 8; _glfw.hints.framebuffer.doublebuffer = GLFW_TRUE; + _glfw.hints.framebuffer.acceleration = GLFW_TRUE; // The default is to select the highest available refresh rate _glfw.hints.refreshRate = GLFW_DONT_CARE; @@ -346,6 +348,9 @@ GLFWAPI void glfwWindowHint(int hint, int value) case GLFW_SRGB_CAPABLE: _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE; return; + case GLFW_ACCELERATION: + _glfw.hints.framebuffer.acceleration = value ? GLFW_TRUE : GLFW_FALSE; + return; case GLFW_RESIZABLE: _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE; return; @@ -897,6 +902,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) return window->autoIconify; case GLFW_DOUBLEBUFFER: return window->doublebuffer; + case GLFW_ACCELERATION: + return window->acceleration; case GLFW_CLIENT_API: return window->context.client; case GLFW_CONTEXT_CREATION_API: diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index 12acbccc..d353f32e 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -383,6 +383,7 @@ int main(int argc, char** argv) int angle_type = GLFW_ANGLE_PLATFORM_TYPE_NONE; bool cocoa_graphics_switching = false; bool disable_xcb_surface = false; + bool acceleration = true; enum { PLATFORM, CLIENT, CONTEXT, BEHAVIOR, DEBUG_CONTEXT, FORWARD, HELP, EXTENSIONS, LAYERS, @@ -390,7 +391,7 @@ int main(int argc, char** argv) REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS, ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS, AUXBUFFERS, SAMPLES, STEREO, SRGB, SINGLEBUFFER, NOERROR_SRSLY, - ANGLE_TYPE, GRAPHICS_SWITCHING, XCB_SURFACE }; + ANGLE_TYPE, GRAPHICS_SWITCHING, XCB_SURFACE, NO_ACCELERATION }; const struct option options[] = { { "platform", 1, NULL, PLATFORM }, @@ -426,6 +427,7 @@ int main(int argc, char** argv) { "angle-type", 1, NULL, ANGLE_TYPE }, { "graphics-switching", 0, NULL, GRAPHICS_SWITCHING }, { "vk-xcb-surface", 0, NULL, XCB_SURFACE }, + { "no-acceleration", 0, NULL, NO_ACCELERATION }, { NULL, 0, NULL, 0 } }; @@ -654,6 +656,9 @@ int main(int argc, char** argv) case XCB_SURFACE: disable_xcb_surface = true; break; + case NO_ACCELERATION: + acceleration = false; + break; default: usage(); exit(EXIT_FAILURE); @@ -708,6 +713,7 @@ int main(int argc, char** argv) glfwWindowHint(GLFW_STEREO, fb_stereo); glfwWindowHint(GLFW_SRGB_CAPABLE, fb_srgb); glfwWindowHint(GLFW_DOUBLEBUFFER, fb_doublebuffer); + glfwWindowHint(GLFW_ACCELERATION, acceleration); glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, cocoa_graphics_switching);