sdl_renderer: fix Metal rendering (#426)

Addresses an issue where the Metal render driver (macOS) could not handle the clipping rectangle {-8192, -8192, 16384, 16384} and would simply draw nothing to the screen. The solution is to ensure the cliprect coordinates are not negative, which also doesn't break the other render drivers.

Co-authored-by: Kristian Bolino <kbolino@kbolino.com>
This commit is contained in:
Kristian Bolino 2022-03-15 10:28:47 -04:00 committed by GitHub
parent f0dccaeeec
commit cbfc8f89e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -19,6 +19,16 @@ NK_API int nk_sdl_handle_event(SDL_Event *evt);
NK_API void nk_sdl_render(enum nk_anti_aliasing);
NK_API void nk_sdl_shutdown(void);
#if SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 22)
/* Metal API does not support cliprects with negative coordinates or large
* dimensions. The issue is fixed in SDL2 with version 2.0.22 but until
* that version is released, the NK_SDL_CLAMP_CLIP_RECT flag can be used to
* ensure the cliprect is itself clipped to the viewport.
* See discussion at https://discourse.libsdl.org/t/rendergeometryraw-producing-different-results-in-metal-vs-opengl/34953
*/
#define NK_SDL_CLAMP_CLIP_RECT
#endif
#endif /* NK_SDL_RENDERER_H_ */
/*
@ -30,6 +40,8 @@ NK_API void nk_sdl_shutdown(void);
*/
#ifdef NK_SDL_RENDERER_IMPLEMENTATION
#include <strings.h>
struct nk_sdl_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
@ -75,6 +87,9 @@ nk_sdl_render(enum nk_anti_aliasing AA)
{
SDL_Rect saved_clip;
#ifdef NK_SDL_CLAMP_CLIP_RECT
SDL_Rect viewport;
#endif
SDL_bool clipping_enabled;
int vs = sizeof(struct nk_sdl_vertex);
size_t vp = offsetof(struct nk_sdl_vertex, position);
@ -116,6 +131,9 @@ nk_sdl_render(enum nk_anti_aliasing AA)
clipping_enabled = SDL_RenderIsClipEnabled(sdl.renderer);
SDL_RenderGetClipRect(sdl.renderer, &saved_clip);
#ifdef NK_SDL_CLAMP_CLIP_RECT
SDL_RenderGetViewport(sdl.renderer, &viewport);
#endif
nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds)
{
@ -127,6 +145,22 @@ nk_sdl_render(enum nk_anti_aliasing AA)
r.y = cmd->clip_rect.y;
r.w = cmd->clip_rect.w;
r.h = cmd->clip_rect.h;
#ifdef NK_SDL_CLAMP_CLIP_RECT
if (r.x < 0) {
r.w += r.x;
r.x = 0;
}
if (r.y < 0) {
r.h += r.y;
r.y = 0;
}
if (r.h > viewport.h) {
r.h = viewport.h;
}
if (r.w > viewport.w) {
r.w = viewport.w;
}
#endif
SDL_RenderSetClipRect(sdl.renderer, &r);
}
@ -182,6 +216,25 @@ nk_sdl_clipboard_copy(nk_handle usr, const char *text, int len)
NK_API struct nk_context*
nk_sdl_init(SDL_Window *win, SDL_Renderer *renderer)
{
#ifndef NK_SDL_CLAMP_CLIP_RECT
SDL_RendererInfo info;
SDL_version runtimeVer;
/* warn for cases where NK_SDL_CLAMP_CLIP_RECT should have been set but isn't */
SDL_GetRendererInfo(renderer, &info);
SDL_GetVersion(&runtimeVer);
if (strncmp("metal", info.name, 5) == 0 &&
SDL_VERSIONNUM(runtimeVer.major, runtimeVer.minor, runtimeVer.patch) < SDL_VERSIONNUM(2, 0, 22))
{
SDL_LogWarn(
SDL_LOG_CATEGORY_APPLICATION,
"renderer is using Metal API but runtime SDL version %d.%d.%d is older than compiled version %d.%d.%d, "
"which may cause issues with rendering",
runtimeVer.major, runtimeVer.minor, runtimeVer.patch,
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL
);
}
#endif
sdl.win = win;
sdl.renderer = renderer;
nk_init_default(&sdl.ctx, 0);