opengl surface/renderer: set surface scaling according to dpi of first monitor. Use that dpi to scale backing texture of canvas renderer. Note: changing monitor isn't handled yet!

This commit is contained in:
martinfouilleul 2023-02-08 18:22:54 +01:00
parent 7fbc4ba270
commit 7cf4c3d925
14 changed files with 144 additions and 87 deletions

View File

@ -1,4 +1,4 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext
cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GL /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib /out:../../bin/perf_text.exe cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GL /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib shcore.lib /out:../../bin/perf_text.exe

View File

@ -81,6 +81,8 @@ int main()
mp_rect rect = {.x = 100, .y = 100, .w = 980, .h = 600}; mp_rect rect = {.x = 100, .y = 100, .w = 980, .h = 600};
mp_window window = mp_window_create(rect, "test", 0); mp_window window = mp_window_create(rect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface, canvas and font //NOTE: create surface, canvas and font
#if defined(OS_MACOS) #if defined(OS_MACOS)
@ -90,12 +92,13 @@ int main()
#else #else
#error "unsupported OS" #error "unsupported OS"
#endif #endif
mg_surface_swap_interval(surface, 0);
mg_canvas canvas = mg_canvas_create(surface); mg_canvas canvas = mg_canvas_create(surface);
mg_font font = create_font(); mg_font font = create_font();
mg_font_extents extents = mg_font_get_extents(font); mg_font_extents extents = mg_font_get_extents(font);
f32 fontScale = mg_font_get_scale_for_em_pixels(font, 12); f32 fontScale = mg_font_get_scale_for_em_pixels(font, 14);
f32 lineHeight = fontScale*(extents.ascent + extents.descent + extents.leading); f32 lineHeight = fontScale*(extents.ascent + extents.descent + extents.leading);
@ -130,14 +133,14 @@ int main()
} }
f32 textX = 10; f32 textX = 10;
f32 textY = 600 - lineHeight; f32 textY = contentRect.h - lineHeight - 10;
mg_surface_prepare(surface); mg_surface_prepare(surface);
mg_set_color_rgba(1, 1, 1, 1); mg_set_color_rgba(1, 1, 1, 1);
mg_clear(); mg_clear();
mg_set_font(font); mg_set_font(font);
mg_set_font_size(12); mg_set_font_size(14);
mg_set_color_rgba(0, 0, 0, 1); mg_set_color_rgba(0, 0, 0, 1);
mg_move_to(textX, textY); mg_move_to(textX, textY);
@ -155,7 +158,7 @@ int main()
break; break;
} }
} }
ASSERT(subIndex < 512 && (startIndex+subIndex)<=codePointCount);
u32 glyphs[512]; u32 glyphs[512];
mg_font_get_glyph_indices(font, (str32){subIndex, codePoints+startIndex}, (str32){512, glyphs}); mg_font_get_glyph_indices(font, (str32){subIndex, codePoints+startIndex}, (str32){512, glyphs});
@ -171,12 +174,10 @@ int main()
startIndex += subIndex; startIndex += subIndex;
} }
f64 startFlushTime = mp_get_time(MP_CLOCK_MONOTONIC);
mg_set_color_rgba(0, 0, 1, 1); mg_set_color_rgba(0, 0, 1, 1);
mg_set_font(font); mg_set_font(font);
mg_set_font_size(12); mg_set_font_size(14);
mg_move_to(50, 50); mg_move_to(10, 10 + lineHeight);
str8 text = str8_pushf(mem_scratch(), str8 text = str8_pushf(mem_scratch(),
"Milepost vector graphics test program (frame time = %fs, fps = %f)...", "Milepost vector graphics test program (frame time = %fs, fps = %f)...",
@ -185,6 +186,8 @@ int main()
mg_text_outlines(text); mg_text_outlines(text);
mg_fill(); mg_fill();
f64 startFlushTime = mp_get_time(MP_CLOCK_MONOTONIC);
mg_flush(); mg_flush();
f64 startPresentTime = mp_get_time(MP_CLOCK_MONOTONIC); f64 startPresentTime = mp_get_time(MP_CLOCK_MONOTONIC);

View File

@ -1,3 +1,3 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers
cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GL /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib /out:../../bin/example_canvas.exe cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GL /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib shcore.lib /out:../../bin/example_canvas.exe

View File

@ -181,10 +181,11 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 shapeCount, u32 v
mg_gl_send_buffers(backend, shapeCount, vertexCount, indexCount); mg_gl_send_buffers(backend, shapeCount, vertexCount, indexCount);
mp_rect frame = mg_surface_get_frame(backend->surface); mp_rect frame = mg_surface_get_frame(backend->surface);
vec2 contentsScaling = mg_surface_contents_scaling(backend->surface);
const int tileSize = 16; const int tileSize = 16;
const int tileCountX = (frame.w + tileSize - 1)/tileSize; const int tileCountX = (frame.w*contentsScaling.x + tileSize - 1)/tileSize;
const int tileCountY = (frame.h + tileSize - 1)/tileSize; const int tileCountY = (frame.h*contentsScaling.y + tileSize - 1)/tileSize;
const int tileArraySize = MG_GL_CANVAS_TILE_ARRAY_SIZE; const int tileArraySize = MG_GL_CANVAS_TILE_ARRAY_SIZE;
//TODO: ensure there's enough space in tile buffer //TODO: ensure there's enough space in tile buffer
@ -208,6 +209,7 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 shapeCount, u32 v
glUniform2ui(1, tileCountX, tileCountY); glUniform2ui(1, tileCountX, tileCountY);
glUniform1ui(2, tileSize); glUniform1ui(2, tileSize);
glUniform1ui(3, tileArraySize); glUniform1ui(3, tileArraySize);
glUniform2f(4, contentsScaling.x, contentsScaling.y);
u32 threadCount = indexCount/3; u32 threadCount = indexCount/3;
glDispatchCompute((threadCount + 255)/256, 1, 1); glDispatchCompute((threadCount + 255)/256, 1, 1);
@ -222,7 +224,7 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 shapeCount, u32 v
glDispatchCompute(tileCountX * tileCountY, 1, 1); glDispatchCompute(tileCountX * tileCountY, 1, 1);
//NOTE: then we fire the fragment shader that will select only triangles in its tile //NOTE: then we fire the drawing shader that will select only triangles in its tile
glUseProgram(backend->drawProgram); glUseProgram(backend->drawProgram);
glBindImageTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); glBindImageTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
@ -231,6 +233,7 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 shapeCount, u32 v
glUniform2ui(1, tileCountX, tileCountY); glUniform2ui(1, tileCountX, tileCountY);
glUniform1ui(2, tileSize); glUniform1ui(2, tileSize);
glUniform1ui(3, tileArraySize); glUniform1ui(3, tileArraySize);
glUniform2f(4, contentsScaling.x, contentsScaling.y);
glDispatchCompute(tileCountX, tileCountY, 1); glDispatchCompute(tileCountX, tileCountY, 1);
@ -330,9 +333,11 @@ mg_canvas_backend* mg_gl_canvas_create(mg_surface surface)
glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GL_CANVAS_TILE_ARRAY_BUFFER_SIZE, 0, GL_DYNAMIC_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GL_CANVAS_TILE_ARRAY_BUFFER_SIZE, 0, GL_DYNAMIC_COPY);
mp_rect frame = mg_surface_get_frame(backend->surface); mp_rect frame = mg_surface_get_frame(backend->surface);
vec2 contentsScaling = mg_surface_contents_scaling(backend->surface);
glGenTextures(1, &backend->outTexture); glGenTextures(1, &backend->outTexture);
glBindTexture(GL_TEXTURE_2D, backend->outTexture); glBindTexture(GL_TEXTURE_2D, backend->outTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, frame.w, frame.h); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, frame.w*contentsScaling.x, frame.h*contentsScaling.y);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

View File

@ -42,8 +42,9 @@ layout(location = 0) uniform uint indexCount;
layout(location = 1) uniform uvec2 tileCount; layout(location = 1) uniform uvec2 tileCount;
layout(location = 2) uniform uint tileSize; layout(location = 2) uniform uint tileSize;
layout(location = 3) uniform uint tileArraySize; layout(location = 3) uniform uint tileArraySize;
layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture; layout(location = 4) uniform vec2 scaling;
layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;
bool is_top_left(ivec2 a, ivec2 b) bool is_top_left(ivec2 a, ivec2 b)
{ {
@ -63,25 +64,25 @@ void main()
uint tileIndex = tileCoord.y * tileCount.x + tileCoord.x; uint tileIndex = tileCoord.y * tileCount.x + tileCoord.x;
uint tileCounter = tileCounterBuffer.elements[tileIndex]; uint tileCounter = tileCounterBuffer.elements[tileIndex];
const float subPixelFactor = 16.; const float subPixelFactor = 256.;
ivec2 centerPoint = ivec2((vec2(pixelCoord) + vec2(0.5, 0.5)) * subPixelFactor); ivec2 centerPoint = ivec2((vec2(pixelCoord) + vec2(0.5, 0.5)) * subPixelFactor);
//* //*
const int sampleCount = 8; const int sampleCount = 8;
ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(1, 3), ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(1, 3)*16,
centerPoint + ivec2(-1, -3), centerPoint + ivec2(-1, -3)*16,
centerPoint + ivec2(5, -1), centerPoint + ivec2(5, -1)*16,
centerPoint + ivec2(-3, 5), centerPoint + ivec2(-3, 5)*16,
centerPoint + ivec2(-5, -5), centerPoint + ivec2(-5, -5)*16,
centerPoint + ivec2(-7, 1), centerPoint + ivec2(-7, 1)*16,
centerPoint + ivec2(3, -7), centerPoint + ivec2(3, -7)*16,
centerPoint + ivec2(7, 7)); centerPoint + ivec2(7, 7)*16);
/*/ /*/
const int sampleCount = 4; const int sampleCount = 4;
ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(-2, 6), ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(-2, 6)*16,
centerPoint + ivec2(6, 2), centerPoint + ivec2(6, 2)*16,
centerPoint + ivec2(-6, -2), centerPoint + ivec2(-6, -2)*16,
centerPoint + ivec2(2, -6)); centerPoint + ivec2(2, -6)*16);
//*/ //*/
//DEBUG //DEBUG
/* /*
@ -132,13 +133,13 @@ void main()
uint i1 = indexBuffer.elements[triangleIndex+1u]; uint i1 = indexBuffer.elements[triangleIndex+1u];
uint i2 = indexBuffer.elements[triangleIndex+2u]; uint i2 = indexBuffer.elements[triangleIndex+2u];
ivec2 p0 = ivec2((vertexBuffer.elements[i0].pos) * subPixelFactor); ivec2 p0 = ivec2((vertexBuffer.elements[i0].pos * scaling) * subPixelFactor);
ivec2 p1 = ivec2((vertexBuffer.elements[i1].pos) * subPixelFactor); ivec2 p1 = ivec2((vertexBuffer.elements[i1].pos * scaling) * subPixelFactor);
ivec2 p2 = ivec2((vertexBuffer.elements[i2].pos) * subPixelFactor); ivec2 p2 = ivec2((vertexBuffer.elements[i2].pos * scaling) * subPixelFactor);
int zIndex = vertexBuffer.elements[i0].zIndex; int zIndex = vertexBuffer.elements[i0].zIndex;
vec4 color = shapeBuffer.elements[zIndex].color; vec4 color = shapeBuffer.elements[zIndex].color;
ivec4 clip = ivec4(round((shapeBuffer.elements[zIndex].clip + vec4(0.5, 0.5, 0.5, 0.5)) * subPixelFactor)); ivec4 clip = ivec4(round((shapeBuffer.elements[zIndex].clip * vec4(scaling, scaling) + vec4(0.5, 0.5, 0.5, 0.5)) * subPixelFactor));
//NOTE(martin): reorder triangle counter-clockwise and compute bias for each edge //NOTE(martin): reorder triangle counter-clockwise and compute bias for each edge
int cw = (p1 - p0).x*(p2 - p0).y - (p1 - p0).y*(p2 - p0).x; int cw = (p1 - p0).x*(p2 - p0).y - (p1 - p0).y*(p2 - p0).x;

View File

@ -40,6 +40,7 @@ layout(location = 0) uniform uint indexCount;
layout(location = 1) uniform uvec2 tileCount; layout(location = 1) uniform uvec2 tileCount;
layout(location = 2) uniform uint tileSize; layout(location = 2) uniform uint tileSize;
layout(location = 3) uniform uint tileArraySize; layout(location = 3) uniform uint tileArraySize;
layout(location = 4) uniform vec2 scaling;
void main() void main()
{ {
@ -53,12 +54,12 @@ void main()
uint i1 = indexBuffer.elements[triangleIndex+1u]; uint i1 = indexBuffer.elements[triangleIndex+1u];
uint i2 = indexBuffer.elements[triangleIndex+2u]; uint i2 = indexBuffer.elements[triangleIndex+2u];
vec2 p0 = vertexBuffer.elements[i0].pos; vec2 p0 = vertexBuffer.elements[i0].pos * scaling;
vec2 p1 = vertexBuffer.elements[i1].pos; vec2 p1 = vertexBuffer.elements[i1].pos * scaling;
vec2 p2 = vertexBuffer.elements[i2].pos; vec2 p2 = vertexBuffer.elements[i2].pos * scaling;
int shapeIndex = vertexBuffer.elements[i0].zIndex; int shapeIndex = vertexBuffer.elements[i0].zIndex;
vec4 clip = shapeBuffer.elements[shapeIndex].clip; vec4 clip = shapeBuffer.elements[shapeIndex].clip * vec4(scaling, scaling);
vec4 fbox = vec4(max(min(min(p0.x, p1.x), p2.x), clip.x), vec4 fbox = vec4(max(min(min(p0.x, p1.x), p2.x), clip.x),
max(min(min(p0.y, p1.y), p2.y), clip.y), max(min(min(p0.y, p1.y), p2.y), clip.y),

View File

@ -331,6 +331,19 @@ void mg_surface_swap_interval(mg_surface surface, int swap)
} }
} }
vec2 mg_surface_contents_scaling(mg_surface surface)
{
DEBUG_ASSERT(__mgData.init);
vec2 scaling = {1, 1};
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData)
{
scaling = surfaceData->contentsScaling(surfaceData);
}
return(scaling);
}
void mg_surface_set_frame(mg_surface surface, mp_rect frame) void mg_surface_set_frame(mg_surface surface, mp_rect frame)
{ {
DEBUG_ASSERT(__mgData.init); DEBUG_ASSERT(__mgData.init);

View File

@ -21,6 +21,7 @@ void mg_surface_destroy(mg_surface surface);
void mg_surface_prepare(mg_surface surface); void mg_surface_prepare(mg_surface surface);
void mg_surface_present(mg_surface surface); void mg_surface_present(mg_surface surface);
void mg_surface_swap_interval(mg_surface surface, int swap); void mg_surface_swap_interval(mg_surface surface, int swap);
vec2 mg_surface_contents_scaling(mg_surface surface);
mp_rect mg_surface_get_frame(mg_surface surface); mp_rect mg_surface_get_frame(mg_surface surface);
void mg_surface_set_frame(mg_surface surface, mp_rect frame); void mg_surface_set_frame(mg_surface surface, mp_rect frame);
bool mg_surface_get_hidden(mg_surface surface); bool mg_surface_get_hidden(mg_surface surface);

View File

@ -28,6 +28,7 @@ typedef void (*mg_surface_destroy_proc)(mg_surface_data* surface);
typedef void (*mg_surface_prepare_proc)(mg_surface_data* surface); typedef void (*mg_surface_prepare_proc)(mg_surface_data* surface);
typedef void (*mg_surface_present_proc)(mg_surface_data* surface); typedef void (*mg_surface_present_proc)(mg_surface_data* surface);
typedef void (*mg_surface_swap_interval_proc)(mg_surface_data* surface, int swap); typedef void (*mg_surface_swap_interval_proc)(mg_surface_data* surface, int swap);
typedef vec2 (*mg_surface_contents_scaling_proc)(mg_surface_data* surface);
typedef mp_rect (*mg_surface_get_frame_proc)(mg_surface_data* surface); typedef mp_rect (*mg_surface_get_frame_proc)(mg_surface_data* surface);
typedef void (*mg_surface_set_frame_proc)(mg_surface_data* surface, mp_rect frame); typedef void (*mg_surface_set_frame_proc)(mg_surface_data* surface, mp_rect frame);
typedef bool (*mg_surface_get_hidden_proc)(mg_surface_data* surface); typedef bool (*mg_surface_get_hidden_proc)(mg_surface_data* surface);
@ -41,6 +42,7 @@ typedef struct mg_surface_data
mg_surface_prepare_proc prepare; mg_surface_prepare_proc prepare;
mg_surface_present_proc present; mg_surface_present_proc present;
mg_surface_swap_interval_proc swapInterval; mg_surface_swap_interval_proc swapInterval;
mg_surface_contents_scaling_proc contentsScaling;
mg_surface_get_frame_proc getFrame; mg_surface_get_frame_proc getFrame;
mg_surface_set_frame_proc setFrame; mg_surface_set_frame_proc setFrame;
mg_surface_get_hidden_proc getHidden; mg_surface_get_hidden_proc getHidden;

View File

@ -156,6 +156,8 @@ void mp_init()
__mpApp.win32.savedConsoleCodePage = GetConsoleOutputCP(); __mpApp.win32.savedConsoleCodePage = GetConsoleOutputCP();
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
} }
} }
@ -258,6 +260,12 @@ LRESULT WinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lParam)
mp_queue_event(&event); mp_queue_event(&event);
} break; } break;
case WM_DPICHANGED:
{
printf("DPI changed!\n");
} break;
//TODO: enter/exit size & move //TODO: enter/exit size & move
case WM_SIZING: case WM_SIZING:
@ -502,6 +510,12 @@ void mp_pump_events(f64 timeout)
// window management // window management
//-------------------------------------------------------------------- //--------------------------------------------------------------------
//WARN: the following header pulls in objbase.h (even with WIN32_LEAN_AND_MEAN), which
// #defines interface to struct... so make sure to #undef interface since it's a
// name we want to be able to use throughout the codebase
#include<ShellScalingApi.h>
#undef interface
mp_window mp_window_create(mp_rect rect, const char* title, mp_window_style style) mp_window mp_window_create(mp_rect rect, const char* title, mp_window_style style)
{ {
WNDCLASS windowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, WNDCLASS windowClass = {.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
@ -516,19 +530,16 @@ mp_window mp_window_create(mp_rect rect, const char* title, mp_window_style styl
goto quit; goto quit;
} }
/* u32 dpiX, dpiY;
//NOTE: get primary monitor dimensions HMONITOR monitor = MonitorFromPoint((POINT){rect.x, rect.y}, MONITOR_DEFAULTTOPRIMARY);
const POINT ptZero = { 0, 0 }; GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
HMONITOR monitor = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
MONITORINFO monitorInfo = {.cbSize = sizeof(MONITORINFO)}; f32 dpiScalingX = (f32)dpiX/96.;
GetMonitorInfo(monitor, &monitorInfo); f32 dpiScalingY = (f32)dpiY/96.;
RECT adjustRect = {rect.x, monitorInfo.rcMonitor.bottom - rect.y - rect.h, rect.w, rect.h};
AdjustWindowRect(&adjustRect, WS_OVERLAPPEDWINDOW, false);
*/
HWND windowHandle = CreateWindow("ApplicationWindowClass", "Test Window", HWND windowHandle = CreateWindow("ApplicationWindowClass", "Test Window",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
rect.w, rect.h, rect.w * dpiScalingX, rect.h * dpiScalingY,
0, 0, windowClass.hInstance, 0); 0, 0, windowClass.hInstance, 0);
if(!windowHandle) if(!windowHandle)
@ -740,7 +751,9 @@ mp_rect mp_window_get_content_rect(mp_window window)
RECT winRect; RECT winRect;
if(GetClientRect(windowData->win32.hWnd, &winRect)) if(GetClientRect(windowData->win32.hWnd, &winRect))
{ {
rect = (mp_rect){0, 0, winRect.right - winRect.left, winRect.bottom - winRect.top}; u32 dpi = GetDpiForWindow(windowData->win32.hWnd);
f32 scale = (float)dpi/96.;
rect = (mp_rect){0, 0, (winRect.right - winRect.left)/scale, (winRect.bottom - winRect.top)/scale};
} }
} }
return(rect); return(rect);

View File

@ -1,36 +1,37 @@
//***************************************************************** //*****************************************************************
// //
// $file: win32_app.h $ // $file: win32_app.h $
// $author: Martin Fouilleul $ // $author: Martin Fouilleul $
// $date: 20/12/2022 $ // $date: 20/12/2022 $
// $revision: $ // $revision: $
// $note: (C) 2022 by Martin Fouilleul - all rights reserved $ // $note: (C) 2022 by Martin Fouilleul - all rights reserved $
// //
//***************************************************************** //*****************************************************************
#ifndef __WIN32_APP_H_ #ifndef __WIN32_APP_H_
#define __WIN32_APP_H_ #define __WIN32_APP_H_
#define WIN32_LEAN_AND_MEAN #include"mp_app.h"
#include<windows.h>
#include"mp_app.h" #define WIN32_LEAN_AND_MEAN
#include<windows.h>
typedef struct win32_window_data
{ typedef struct win32_window_data
HWND hWnd; {
HWND hWnd;
} win32_window_data;
} win32_window_data;
#define MP_PLATFORM_WINDOW_DATA win32_window_data win32;
#define MP_PLATFORM_WINDOW_DATA win32_window_data win32;
typedef struct win32_app_data
{ typedef struct win32_app_data
u32 savedConsoleCodePage; {
u32 savedConsoleCodePage;
int mouseCaptureMask;
bool mouseTracked; int mouseCaptureMask;
bool mouseTracked;
} win32_app_data;
} win32_app_data;
#define MP_PLATFORM_APP_DATA win32_app_data win32;
#define MP_PLATFORM_APP_DATA win32_app_data win32;
#endif __WIN32_APP_H_
#endif __WIN32_APP_H_

View File

@ -44,6 +44,8 @@
GL_PROC(GLDISPATCHCOMPUTE, glDispatchCompute) \ GL_PROC(GLDISPATCHCOMPUTE, glDispatchCompute) \
GL_PROC(GLUNIFORM1UI, glUniform1ui) \ GL_PROC(GLUNIFORM1UI, glUniform1ui) \
GL_PROC(GLUNIFORM2UI, glUniform2ui) \ GL_PROC(GLUNIFORM2UI, glUniform2ui) \
GL_PROC(GLUNIFORM1F, glUniform1f) \
GL_PROC(GLUNIFORM2F, glUniform2f) \
GL_PROC(GLBINDIMAGETEXTURE, glBindImageTexture) \ GL_PROC(GLBINDIMAGETEXTURE, glBindImageTexture) \
GL_PROC(GLACTIVETEXTURE, glActiveTexture) \ GL_PROC(GLACTIVETEXTURE, glActiveTexture) \
GL_PROC(GLUNIFORM1I, glUniform1i) \ GL_PROC(GLUNIFORM1I, glUniform1i) \

View File

@ -6,12 +6,11 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#define WIN32_GL_LOADER_IMPL #define WIN32_GL_LOADER_IMPL
#include"win32_gl_loader.h" #include"win32_gl_loader.h"
#include"win32_app.h"
#include"graphics_internal.h" #include"graphics_internal.h"
#include"win32_app.h"
typedef struct mg_gl_surface typedef struct mg_gl_surface
{ {
@ -20,6 +19,7 @@ typedef struct mg_gl_surface
HWND hWnd; HWND hWnd;
HDC hDC; HDC hDC;
HGLRC glContext; HGLRC glContext;
vec2 contentsScaling;
} mg_gl_surface; } mg_gl_surface;
@ -48,13 +48,24 @@ void mg_gl_surface_swap_interval(mg_surface_data* interface, int swap)
wglSwapIntervalEXT(swap); wglSwapIntervalEXT(swap);
} }
vec2 mg_gl_contents_scaling(mg_surface_data* interface)
{
mg_gl_surface* surface = (mg_gl_surface*)interface;
return(surface->contentsScaling);
}
mp_rect mg_gl_surface_get_frame(mg_surface_data* interface) mp_rect mg_gl_surface_get_frame(mg_surface_data* interface)
{ {
mg_gl_surface* surface = (mg_gl_surface*)interface; mg_gl_surface* surface = (mg_gl_surface*)interface;
RECT rect = {0}; RECT rect = {0};
GetClientRect(surface->hWnd, &rect); GetClientRect(surface->hWnd, &rect);
mp_rect res = {rect.left, rect.bottom, rect.right - rect.left, rect.bottom - rect.top}; vec2 scale = surface->contentsScaling;
mp_rect res = {rect.left/scale.x,
rect.bottom/scale.y,
(rect.right - rect.left)/scale.x,
(rect.bottom - rect.top)/scale.y};
return(res); return(res);
} }
@ -200,6 +211,7 @@ mg_surface mg_gl_surface_create_for_window(mp_window window)
surface->interface.prepare = mg_gl_surface_prepare; surface->interface.prepare = mg_gl_surface_prepare;
surface->interface.present = mg_gl_surface_present; surface->interface.present = mg_gl_surface_present;
surface->interface.swapInterval = mg_gl_surface_swap_interval; surface->interface.swapInterval = mg_gl_surface_swap_interval;
surface->interface.contentsScaling = mg_gl_contents_scaling;
surface->interface.getFrame = mg_gl_surface_get_frame; surface->interface.getFrame = mg_gl_surface_get_frame;
//TODO: get/set frame/hidden //TODO: get/set frame/hidden
@ -207,6 +219,9 @@ mg_surface mg_gl_surface_create_for_window(mp_window window)
surface->hDC = hDC; surface->hDC = hDC;
surface->glContext = glContext; surface->glContext = glContext;
u32 dpi = GetDpiForWindow(windowData->win32.hWnd);
surface->contentsScaling = (vec2){(float)dpi/96., (float)dpi/96.};
surfaceHandle = mg_surface_alloc_handle((mg_surface_data*)surface); surfaceHandle = mg_surface_alloc_handle((mg_surface_data*)surface);
} }

View File

@ -10,7 +10,7 @@ Canvas renderer perf
by subpixel precision and truncating... -> ie sampling at the middle of pixels vs at integer coordinates... by subpixel precision and truncating... -> ie sampling at the middle of pixels vs at integer coordinates...
[ ] What alignment gives crisp-ier lines? [ ] What alignment gives crisp-ier lines?
[>] Add surface scaling for high dpi surfaces [>] Add surface scaling for high dpi surfaces and check that our fonts are renderer smoothly
[x] Allow setting swap interval [x] Allow setting swap interval
[!] Allow swap interval of 0 on macos [!] Allow swap interval of 0 on macos