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:
parent
7fbc4ba270
commit
7cf4c3d925
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -10,9 +10,10 @@
|
||||||
#ifndef __WIN32_APP_H_
|
#ifndef __WIN32_APP_H_
|
||||||
#define __WIN32_APP_H_
|
#define __WIN32_APP_H_
|
||||||
|
|
||||||
|
#include"mp_app.h"
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include<windows.h>
|
#include<windows.h>
|
||||||
#include"mp_app.h"
|
|
||||||
|
|
||||||
typedef struct win32_window_data
|
typedef struct win32_window_data
|
||||||
{
|
{
|
||||||
|
|
|
@ -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) \
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
todo.txt
2
todo.txt
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue