From 9a6c66912bd43b98ab679e66944fe656de52fb4c Mon Sep 17 00:00:00 2001 From: Philosoph228 Date: Wed, 2 Apr 2025 11:54:35 +0500 Subject: [PATCH] Implement bit flags to toggle GDI renderer features Instead of `gdi_fabulous` introduced some bit flags for enabling/disabling features individually. Mainly for testing and benchmarking purposes of these features until we decide the best implementation for each of them. So they are enabled by setting flags with `Clay_Win32_SetRendererFlags()` in user code (demo in this case) --- examples/win32_gdi/main.c | 2 ++ renderers/win32_gdi/clay_renderer_gdi.c | 40 ++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/examples/win32_gdi/main.c b/examples/win32_gdi/main.c index 218042c..e2e44fd 100644 --- a/examples/win32_gdi/main.c +++ b/examples/win32_gdi/main.c @@ -160,6 +160,8 @@ int APIENTRY WinMain( Clay_Arena clayMemory = Clay_CreateArenaWithCapacityAndMemory(clayRequiredMemory, malloc(clayRequiredMemory)); Clay_Initialize(clayMemory, (Clay_Dimensions){.width = 800, .height = 600}, (Clay_ErrorHandler){HandleClayErrors}); // This final argument is new since the video was published + Clay_Win32_SetRendererFlags(CLAYGDI_RF_ALPHABLEND | CLAYGDI_RF_SMOOTHCORNERS); + // Initialize clay fonts and text drawing fonts[FONT_ID_BODY_16] = Clay_Win32_SimpleCreateFont("resources/Roboto-Regular.ttf", "Roboto", -11, FW_NORMAL); Clay_SetMeasureTextFunction(Clay_Win32_MeasureText, fonts); diff --git a/renderers/win32_gdi/clay_renderer_gdi.c b/renderers/win32_gdi/clay_renderer_gdi.c index c44c876..d9f8504 100644 --- a/renderers/win32_gdi/clay_renderer_gdi.c +++ b/renderers/win32_gdi/clay_renderer_gdi.c @@ -9,7 +9,7 @@ HDC renderer_hdcMem = {0}; HBITMAP renderer_hbmMem = {0}; HANDLE renderer_hOld = {0}; -bool gdi_fabulous = true; +DWORD g_dwGdiRenderFlags; #ifndef RECTWIDTH #define RECTWIDTH(rc) ((rc).right - (rc).left) @@ -18,6 +18,31 @@ bool gdi_fabulous = true; #define RECTHEIGHT(rc) ((rc).bottom - (rc).top) #endif +// Renderer options bit flags +// RF clearly stated in the name to avoid confusion with possible macro definitions for other purposes +#define CLAYGDI_RF_ALPHABLEND 0x00000001 +#define CLAYGDI_RF_SMOOTHCORNERS 0x00000002 +// These are bitflags, not indexes. Next would be 0x00000004 + +inline DWORD Clay_Win32_GetRendererFlags() { return g_dwGdiRenderFlags; } + +// Replaces the rendering flags with new ones provided +inline void Clay_Win32_SetRendererFlags(DWORD dwFlags) { g_dwGdiRenderFlags = dwFlags; } + +// Returns `true` if flags were modified +inline bool Clay_Win32_ModifyRendererFlags(DWORD dwRemove, DWORD dwAdd) +{ + DWORD dwSavedFlags = g_dwGdiRenderFlags; + DWORD dwNewFlags = (dwSavedFlags & ~dwRemove) | dwAdd; + + if (dwSavedFlags == dwNewFlags) + return false; + + Clay_Win32_SetRendererFlags(dwNewFlags); + return true; +} + + /*----------------------------------------------------------------------------+ | Math stuff start | +----------------------------------------------------------------------------*/ @@ -99,7 +124,6 @@ static inline Clay_Color ColorBlend(Clay_Color base, Clay_Color overlay, float f static float RoundedRectPixelCoverage(int x, int y, const Clay_CornerRadius radius, int width, int height) { // Check if the pixel is in one of the four rounded corners - if (x < radius.topLeft && y < radius.topLeft) { // Top-left corner float dx = radius.topLeft - x - 1; @@ -318,6 +342,7 @@ void Clay_Win32_Render(HWND hwnd, Clay_RenderCommandArray renderCommands, HFONT* } case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: { + DWORD dwFlags = Clay_Win32_GetRendererFlags(); Clay_RectangleRenderData rrd = renderCommand->renderData.rectangle; RECT r = rc; @@ -326,13 +351,20 @@ void Clay_Win32_Render(HWND hwnd, Clay_RenderCommandArray renderCommands, HFONT* r.right = boundingBox.x + boundingBox.width; r.bottom = boundingBox.y + boundingBox.height; - bool translucid = rrd.backgroundColor.a > 0.0f && rrd.backgroundColor.a < 255.0f; + bool translucid = false; + // There is need to check that only if alphablending is enabled. + // In other case the blending will be always opaque and we can jump to simpler FillRgn/Rect + if (dwFlags & CLAYGDI_RF_ALPHABLEND) + translucid = rrd.backgroundColor.a > 0.0f && rrd.backgroundColor.a < 255.0f; + bool has_rounded_corners = rrd.cornerRadius.topLeft > 0.0f || rrd.cornerRadius.topRight > 0.0f || rrd.cornerRadius.bottomLeft > 0.0f || rrd.cornerRadius.bottomRight > 0.0f; - if (gdi_fabulous && (translucid || has_rounded_corners)) + // We go here if CLAYGDI_RF_SMOOTHCORNERS flag is set and one of the corners is rounded + // Also we go here if GLAYGDI_RF_ALPHABLEND flag is set and the fill color is translucid + if ((dwFlags & CLAYGDI_RF_ALPHABLEND) && translucid || (dwFlags & CLAYGDI_RF_SMOOTHCORNERS) && has_rounded_corners) { __Clay_Win32_FillRoundRect(renderer_hdcMem, &r, rrd.backgroundColor, rrd.cornerRadius); }