Skip to content

Commit

Permalink
Add GLFW_CONTEXT_RENDERER
Browse files Browse the repository at this point in the history
This window hint allows choosing between hardware and software renderers
(where available) for the created OpenGL or OpenGL ES context.

Fixes glfw#589.
  • Loading branch information
elmindreda authored and HinTak committed Jun 4, 2024
1 parent 37e0098 commit 46ff90e
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 11 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ information on what to include when reporting a bug.
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
- [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to
`GLFW_NATIVE_CONTEXT_API` (#2518)
- Added `GLFW_CONTEXT_RENDERER` window hint and `GLFW_HARDWARE_RENDERER` and
`GLFW_SOFTWARE_RENDERER` hint values (#589)


## Contact
Expand Down
6 changes: 6 additions & 0 deletions docs/window.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,11 @@ does not update the window contents when its buffers are swapped. Use OpenGL
functions or the OSMesa native access functions @ref glfwGetOSMesaColorBuffer
and @ref glfwGetOSMesaDepthBuffer to retrieve the framebuffer contents.
@anchor GLFW_CONTEXT_RENDERER_hint
__GLFW_CONTEXT_RENDERER__ specifies whether to create the context using
a hardware or software renderer, if that is possible to control on the current
platform.
@anchor GLFW_CONTEXT_VERSION_MAJOR_hint
@anchor GLFW_CONTEXT_VERSION_MINOR_hint
__GLFW_CONTEXT_VERSION_MAJOR__ and __GLFW_CONTEXT_VERSION_MINOR__ specify the
Expand Down Expand Up @@ -566,6 +571,7 @@ GLFW_SRGB_CAPABLE | `GLFW_FALSE` | `GLFW_TRUE` or `GL
GLFW_DOUBLEBUFFER | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_CLIENT_API | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`
GLFW_CONTEXT_CREATION_API | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API`, `GLFW_EGL_CONTEXT_API` or `GLFW_OSMESA_CONTEXT_API`
GLFW_CONTEXT_RENDERER | `GLFW_HARDWARE_RENDERER` | `GLFW_HARDWARE_RENDERER` or `GLFW_SOFTWARE_RENDERER`
GLFW_CONTEXT_VERSION_MAJOR | 1 | Any valid major version number of the chosen client API
GLFW_CONTEXT_VERSION_MINOR | 0 | Any valid minor version number of the chosen client API
GLFW_CONTEXT_ROBUSTNESS | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET`
Expand Down
5 changes: 5 additions & 0 deletions include/GLFW/glfw3.h
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,8 @@ extern "C" {
* [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint) window hint for
* compatibility with earlier versions.
*/
#define GLFW_CONTEXT_RENDERER 0x0002200E

#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
/*! @brief macOS specific
* [window hint](@ref GLFW_COCOA_FRAME_NAME_hint).
Expand Down Expand Up @@ -1180,6 +1182,9 @@ extern "C" {
#define GLFW_WAYLAND_PREFER_LIBDECOR 0x00038001
#define GLFW_WAYLAND_DISABLE_LIBDECOR 0x00038002

#define GLFW_HARDWARE_RENDERER 0x00039001
#define GLFW_SOFTWARE_RENDERER 0x00039002

#define GLFW_ANY_POSITION 0x80000000

/*! @defgroup shapes Standard cursor shapes
Expand Down
9 changes: 9 additions & 0 deletions src/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
return GLFW_FALSE;
}

if (ctxconfig->renderer != GLFW_HARDWARE_RENDERER &&
ctxconfig->renderer != GLFW_SOFTWARE_RENDERER)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid context renderer 0x%08X",
ctxconfig->renderer);
return GLFW_FALSE;
}

if (ctxconfig->client != GLFW_NO_API &&
ctxconfig->client != GLFW_OPENGL_API &&
ctxconfig->client != GLFW_OPENGL_ES_API)
Expand Down
3 changes: 3 additions & 0 deletions src/glx_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,9 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
return GLFW_FALSE;
}

if (ctxconfig->renderer == GLFW_SOFTWARE_RENDERER)
setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);

if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
if (!_glfw.glx.ARB_create_context ||
Expand Down
1 change: 1 addition & 0 deletions src/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ struct _GLFWctxconfig
int profile;
int robustness;
int release;
int renderer;
_GLFWwindow* share;
struct {
GLFWbool offline;
Expand Down
12 changes: 11 additions & 1 deletion src/nsgl_context.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <unistd.h>
#include <math.h>
#include <assert.h>
#include <OpenGL/CGLRenderers.h>


static void makeContextCurrentNSGL(_GLFWwindow* window)
{
Expand Down Expand Up @@ -225,9 +227,17 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
NSOpenGLPixelFormatAttribute attribs[40];
int index = 0;

ADD_ATTRIB(NSOpenGLPFAAccelerated);
ADD_ATTRIB(NSOpenGLPFAClosestPolicy);

if (ctxconfig->renderer == GLFW_HARDWARE_RENDERER)
{
ADD_ATTRIB(NSOpenGLPFAAccelerated);
}
else if (ctxconfig->renderer == GLFW_SOFTWARE_RENDERER)
{
SET_ATTRIB(NSOpenGLPFARendererID, kCGLRendererGenericFloatID);
}

if (ctxconfig->nsgl.offline)
{
ADD_ATTRIB(NSOpenGLPFAAllowOfflineRenderers);
Expand Down
35 changes: 30 additions & 5 deletions src/wgl_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,22 @@ 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 (ctxconfig->renderer == GLFW_HARDWARE_RENDERER)
{
if (FIND_ATTRIB_VALUE(WGL_ACCELERATION_ARB) ==
WGL_NO_ACCELERATION_ARB)
{
continue;
}
}
else if (ctxconfig->renderer == GLFW_SOFTWARE_RENDERER)
{
if (FIND_ATTRIB_VALUE(WGL_ACCELERATION_ARB) !=
WGL_NO_ACCELERATION_ARB)
{
continue;
}
}

if (FIND_ATTRIB_VALUE(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer)
continue;
Expand Down Expand Up @@ -235,10 +249,21 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
continue;
}

if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
(pfd.dwFlags & PFD_GENERIC_FORMAT))
if (ctxconfig->renderer == GLFW_HARDWARE_RENDERER)
{
continue;
if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
(pfd.dwFlags & PFD_GENERIC_FORMAT))
{
continue;
}
}
else if (ctxconfig->renderer == GLFW_SOFTWARE_RENDERER)
{
if ((pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
!(pfd.dwFlags & PFD_GENERIC_FORMAT))
{
continue;
}
}

if (pfd.iPixelType != PFD_TYPE_RGBA)
Expand Down
12 changes: 8 additions & 4 deletions src/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,11 @@ void glfwDefaultWindowHints(void)

// The default is OpenGL with minimum version 1.0
memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
_glfw.hints.context.client = GLFW_OPENGL_API;
_glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
_glfw.hints.context.major = 1;
_glfw.hints.context.minor = 0;
_glfw.hints.context.client = GLFW_OPENGL_API;
_glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
_glfw.hints.context.renderer = GLFW_HARDWARE_RENDERER;
_glfw.hints.context.major = 1;
_glfw.hints.context.minor = 0;

// The default is a focused, visible, resizable window with decorations
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
Expand Down Expand Up @@ -404,6 +405,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_CONTEXT_CREATION_API:
_glfw.hints.context.source = value;
return;
case GLFW_CONTEXT_RENDERER:
_glfw.hints.context.renderer = value;
return;
case GLFW_CONTEXT_VERSION_MAJOR:
_glfw.hints.context.major = value;
return;
Expand Down
20 changes: 19 additions & 1 deletion tests/glfwinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@
#define PLATFORM_NAME_X11 "x11"
#define PLATFORM_NAME_NULL "null"

#define RENDERER_NAME_HW "hw"
#define RENDERER_NAME_SW "sw"

static void usage(void)
{
printf("Usage: glfwinfo [OPTION]...\n");
Expand All @@ -92,6 +95,9 @@ static void usage(void)
API_NAME_NATIVE " or "
API_NAME_EGL " or "
API_NAME_OSMESA ")\n");
printf(" --renderer=RENDERER the renderer to use ("
RENDERER_NAME_HW " or "
RENDERER_NAME_SW ")\n");
printf(" -d, --debug request a debug context\n");
printf(" -f, --forward require a forward-compatible context\n");
printf(" -h, --help show this help\n");
Expand Down Expand Up @@ -384,7 +390,7 @@ int main(int argc, char** argv)
bool cocoa_graphics_switching = false;
bool disable_xcb_surface = false;

enum { PLATFORM, CLIENT, CONTEXT, BEHAVIOR, DEBUG_CONTEXT, FORWARD, HELP,
enum { PLATFORM, CLIENT, CONTEXT, RENDERER, BEHAVIOR, DEBUG_CONTEXT, FORWARD, HELP,
EXTENSIONS, LAYERS,
MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION,
REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS,
Expand All @@ -397,6 +403,7 @@ int main(int argc, char** argv)
{ "behavior", 1, NULL, BEHAVIOR },
{ "client-api", 1, NULL, CLIENT },
{ "context-api", 1, NULL, CONTEXT },
{ "renderer", 1, NULL, RENDERER },
{ "debug", 0, NULL, DEBUG_CONTEXT },
{ "forward", 0, NULL, FORWARD },
{ "help", 0, NULL, HELP },
Expand Down Expand Up @@ -490,6 +497,17 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE);
}
break;
case RENDERER:
if (strcasecmp(optarg, RENDERER_NAME_HW) == 0)
glfwWindowHint(GLFW_CONTEXT_RENDERER, GLFW_HARDWARE_RENDERER);
else if (strcasecmp(optarg, RENDERER_NAME_SW) == 0)
glfwWindowHint(GLFW_CONTEXT_RENDERER, GLFW_SOFTWARE_RENDERER);
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 'd':
case DEBUG_CONTEXT:
context_debug = true;
Expand Down

0 comments on commit 46ff90e

Please sign in to comment.