From 3816e85592b5c68eeea4ed00001692f910a50c82 Mon Sep 17 00:00:00 2001 From: martinfouilleul Date: Tue, 25 Jul 2023 14:18:02 +0200 Subject: [PATCH] [win32, surface] always resize surface to parent window's client area --- examples/canvas/main.c | 3 ++ src/gl_canvas.c | 65 ++++++++++++++++++++---------- src/graphics.h | 3 +- src/graphics_surface.c | 35 ++++++----------- src/graphics_surface.h | 37 +----------------- src/win32_app.c | 89 ++++++++++-------------------------------- src/win32_app.h | 1 - 7 files changed, 84 insertions(+), 149 deletions(-) diff --git a/examples/canvas/main.c b/examples/canvas/main.c index eb5c0c9..1596add 100644 --- a/examples/canvas/main.c +++ b/examples/canvas/main.c @@ -161,6 +161,9 @@ int main() mg_set_color_rgba(0, 1, 1, 1); mg_clear(); + mg_set_color_rgba(1, 0, 1, 1); + mg_rectangle_fill(0, 0, 100, 100); + // head mg_set_color_rgba(1, 1, 0, 1); diff --git a/src/gl_canvas.c b/src/gl_canvas.c index cc1a635..bff7ea7 100644 --- a/src/gl_canvas.c +++ b/src/gl_canvas.c @@ -130,6 +130,10 @@ typedef struct mg_gl_canvas_backend mg_canvas_backend interface; mg_wgl_surface* surface; + int msaaCount; + vec2 frameSize; + + // gl stuff GLuint vao; GLuint pathSetup; @@ -155,17 +159,12 @@ typedef struct mg_gl_canvas_backend GLuint tileOpCountBuffer; GLuint screenTilesBuffer; GLuint rasterDispatchBuffer; - GLuint dummyVertexBuffer; - int msaaCount; - vec2 frameSize; - //encoding context int pathCount; int eltCount; - ///////////////// int pathBatchStart; int eltBatchStart; @@ -1201,10 +1200,28 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend, backend->eltBatchStart = backend->eltCount; } -///////////////////////////////////////////////////////////////////////// -//TODO -void mg_gl_canvas_resize(mg_gl_canvas_backend* backend, vec2 size); -///////////////////////////////////////////////////////////////////////// +void mg_gl_canvas_resize(mg_gl_canvas_backend* backend, vec2 size) +{ + int tileSize = MG_GL_TILE_SIZE; + int nTilesX = (int)(size.x + tileSize - 1)/tileSize; + int nTilesY = (int)(size.y + tileSize - 1)/tileSize; + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->screenTilesBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, nTilesX*nTilesY*sizeof(mg_gl_screen_tile), 0, GL_DYNAMIC_COPY); + + if(backend->outTexture) + { + //NOTE: do we need to explicitly glDeleteTextures()? + glDeleteTextures(1, &backend->outTexture); + glGenTextures(1, &backend->outTexture); + glBindTexture(GL_TEXTURE_2D, backend->outTexture); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, size.x, size.y); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + backend->frameSize = size; +} void mg_gl_canvas_render(mg_canvas_backend* interface, mg_color clearColor, @@ -1224,23 +1241,29 @@ void mg_gl_canvas_render(mg_canvas_backend* interface, backend->bufferSync[backend->bufferIndex] = 0; } - //TODO update screen tiles buffer size + //NOTE update screen tiles buffer size mg_wgl_surface* surface = backend->surface; - mp_rect frame = surface->interface.getFrame((mg_surface_data*)surface); + vec2 surfaceSize = surface->interface.getSize((mg_surface_data*)surface); vec2 contentsScaling = surface->interface.contentsScaling((mg_surface_data*)surface); - //TODO support scaling in both axes + //TODO support scaling in both axes? f32 scale = contentsScaling.x; - vec2 viewportSize = {frame.w * scale, frame.h * scale}; + vec2 viewportSize = {surfaceSize.x * scale, surfaceSize.y * scale}; int tileSize = MG_GL_TILE_SIZE; - int nTilesX = (int)(frame.w * scale + tileSize - 1)/tileSize; - int nTilesY = (int)(frame.h * scale + tileSize - 1)/tileSize; + int nTilesX = (int)(viewportSize.x + tileSize - 1)/tileSize; + int nTilesY = (int)(viewportSize.y + tileSize - 1)/tileSize; if(viewportSize.x != backend->frameSize.x || viewportSize.y != backend->frameSize.y) { - //TODO: mg_gl_canvas_resize(backend, viewportSize); + mg_gl_canvas_resize(backend, viewportSize); } + ///////////////////////////////////////////////////////////////////////////////////////////////////// + //TODO: the surface's frame and the underlying window/view rect are not necessarily the same. + // we should set the viewport to cover the whole surface's frame, so it might not start at (0, 0) + ///////////////////////////////////////////////////////////////////////////////////////////////////// + glViewport(0, 0, viewportSize.x, viewportSize.y); + //NOTE: clear screen and reset input buffer offsets glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); @@ -1544,12 +1567,14 @@ mg_canvas_backend* gl_canvas_backend_create(mg_wgl_surface* surface) } //NOTE: create out texture - mp_rect frame = surface->interface.getFrame((mg_surface_data*)surface); + vec2 size = surface->interface.getSize((mg_surface_data*)surface); vec2 scale = surface->interface.contentsScaling((mg_surface_data*)surface); + backend->frameSize = (vec2){size.x * scale.x, size.y * scale.y}; + glGenTextures(1, &backend->outTexture); glBindTexture(GL_TEXTURE_2D, backend->outTexture); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, frame.w*scale.x, frame.h*scale.y); + glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, backend->frameSize.x, backend->frameSize.y); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1611,8 +1636,8 @@ mg_canvas_backend* gl_canvas_backend_create(mg_wgl_surface* surface) glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int), 0, GL_DYNAMIC_COPY); int tileSize = MG_GL_TILE_SIZE; - int nTilesX = (int)(frame.w * scale.x + tileSize - 1)/tileSize; - int nTilesY = (int)(frame.h * scale.y + tileSize - 1)/tileSize; + int nTilesX = (int)(backend->frameSize.x + tileSize - 1)/tileSize; + int nTilesY = (int)(backend->frameSize.y + tileSize - 1)/tileSize; glGenBuffers(1, &backend->screenTilesBuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->screenTilesBuffer); diff --git a/src/graphics.h b/src/graphics.h index 2eac71a..3a9a875 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -105,9 +105,8 @@ MP_API void mg_surface_present(mg_surface surface); MP_API void mg_surface_deselect(void); MP_API void mg_surface_swap_interval(mg_surface surface, int swap); +MP_API vec2 mg_surface_get_size(mg_surface surface); MP_API vec2 mg_surface_contents_scaling(mg_surface surface); -MP_API mp_rect mg_surface_get_frame(mg_surface surface); -MP_API void mg_surface_set_frame(mg_surface surface, mp_rect frame); MP_API bool mg_surface_get_hidden(mg_surface surface); MP_API void mg_surface_set_hidden(mg_surface surface, bool hidden); diff --git a/src/graphics_surface.c b/src/graphics_surface.c index 5715f89..9acc7a9 100644 --- a/src/graphics_surface.c +++ b/src/graphics_surface.c @@ -263,6 +263,18 @@ void mg_surface_swap_interval(mg_surface surface, int swap) } } +vec2 mg_surface_get_size(mg_surface surface) +{ + DEBUG_ASSERT(__mgData.init); + vec2 size = {0}; + mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); + if(surfaceData && surfaceData->getSize) + { + size = surfaceData->getSize(surfaceData); + } + return(size); +} + vec2 mg_surface_contents_scaling(mg_surface surface) { DEBUG_ASSERT(__mgData.init); @@ -275,29 +287,6 @@ vec2 mg_surface_contents_scaling(mg_surface surface) return(scaling); } - -void mg_surface_set_frame(mg_surface surface, mp_rect frame) -{ - DEBUG_ASSERT(__mgData.init); - mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); - if(surfaceData && surfaceData->setFrame) - { - surfaceData->setFrame(surfaceData, frame); - } -} - -mp_rect mg_surface_get_frame(mg_surface surface) -{ - DEBUG_ASSERT(__mgData.init); - mp_rect res = {0}; - mg_surface_data* surfaceData = mg_surface_data_from_handle(surface); - if(surfaceData && surfaceData->getFrame) - { - res = surfaceData->getFrame(surfaceData); - } - return(res); -} - void mg_surface_set_hidden(mg_surface surface, bool hidden) { DEBUG_ASSERT(__mgData.init); diff --git a/src/graphics_surface.h b/src/graphics_surface.h index fed7d6c..0dca19b 100644 --- a/src/graphics_surface.h +++ b/src/graphics_surface.h @@ -26,9 +26,8 @@ typedef void (*mg_surface_prepare_proc)(mg_surface_data* surface); typedef void (*mg_surface_deselect_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 vec2 (*mg_surface_get_size_proc)(mg_surface_data* surface); typedef vec2 (*mg_surface_contents_scaling_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 bool (*mg_surface_get_hidden_proc)(mg_surface_data* surface); typedef void (*mg_surface_set_hidden_proc)(mg_surface_data* surface, bool hidden); typedef void* (*mg_surface_native_layer_proc)(mg_surface_data* surface); @@ -45,9 +44,8 @@ typedef struct mg_surface_data mg_surface_present_proc present; mg_surface_deselect_proc deselect; mg_surface_swap_interval_proc swapInterval; + mg_surface_get_size_proc getSize; mg_surface_contents_scaling_proc contentsScaling; - mg_surface_get_frame_proc getFrame; - mg_surface_set_frame_proc setFrame; mg_surface_get_hidden_proc getHidden; mg_surface_set_hidden_proc setHidden; mg_surface_native_layer_proc nativeLayer; @@ -79,34 +77,6 @@ typedef struct mg_image_data } mg_image_data; -typedef struct mg_vertex_layout -{ - u32 maxVertexCount; - u32 maxIndexCount; - - char* posBuffer; - u32 posStride; - - char* cubicBuffer; - u32 cubicStride; - - char* shapeIndexBuffer; - u32 shapeIndexStride; - - char* colorBuffer; - u32 colorStride; - - char* clipBuffer; - u32 clipStride; - - char* uvTransformBuffer; - u32 uvTransformStride; - - char* indexBuffer; - u32 indexStride; - -} mg_vertex_layout; - typedef void (*mg_canvas_backend_destroy_proc)(mg_canvas_backend* backend); typedef void (*mg_canvas_backend_begin_proc)(mg_canvas_backend* backend, mg_color clearColor); typedef void (*mg_canvas_backend_end_proc)(mg_canvas_backend* backend); @@ -133,8 +103,6 @@ typedef void (*mg_canvas_backend_render_proc)(mg_canvas_backend* backend, typedef struct mg_canvas_backend { -// mg_vertex_layout vertexLayout; - mg_canvas_backend_destroy_proc destroy; mg_canvas_backend_begin_proc begin; mg_canvas_backend_end_proc end; @@ -144,7 +112,6 @@ typedef struct mg_canvas_backend mg_canvas_backend_image_destroy_proc imageDestroy; mg_canvas_backend_image_upload_region_proc imageUploadRegion; - mg_canvas_backend_render_proc render; } mg_canvas_backend; diff --git a/src/win32_app.c b/src/win32_app.c index 8342131..70fb48b 100644 --- a/src/win32_app.c +++ b/src/win32_app.c @@ -247,39 +247,6 @@ static void process_wheel_event(mp_window_data* window, f32 x, f32 y) mp_queue_event(&event); } -void mg_win32_layer_set_frame(mp_layer* layer, mp_rect frame) -{ - layer->userFrame = frame; - - HWND parent = GetParent(layer->hWnd); - - RECT clientRect; - GetClientRect(parent, &clientRect); - POINT point = {0}; - ClientToScreen(layer->hWnd, &point); - - u32 dpi = GetDpiForWindow(layer->hWnd); - vec2 scale = (vec2){(float)dpi/96., (float)dpi/96.}; - - int parentWidth = (clientRect.right - clientRect.left)/scale.x; - int parentHeight = (clientRect.bottom - clientRect.top)/scale.y; - - int minX = Clamp(frame.x, 0, parentWidth); - int maxX = Clamp(frame.x + frame.w, 0, parentWidth); - int minY = Clamp(frame.y, 0, parentHeight); - int maxY = Clamp(frame.y + frame.h, 0, parentHeight); - - SetWindowPos(layer->hWnd, - HWND_TOP, - point.x + minX * scale.x, - point.y + minY * scale.y, - (maxX - minX) * scale.x, - (maxY - minY) * scale.y, - SWP_NOACTIVATE | SWP_NOZORDER); - - //TODO test if we should we guard against 0-width windows -} - static void win32_update_child_layers(mp_window_data* window) { RECT clientRect; @@ -287,29 +254,19 @@ static void win32_update_child_layers(mp_window_data* window) POINT point = {0}; ClientToScreen(window->win32.hWnd, &point); - u32 dpi = GetDpiForWindow(window->win32.hWnd); - vec2 scale = (vec2){(float)dpi/96., (float)dpi/96.}; - - int parentWidth = (clientRect.right - clientRect.left)/scale.x; - int parentHeight = (clientRect.bottom - clientRect.top)/scale.y; + int clientWidth = (clientRect.right - clientRect.left); + int clientHeight = (clientRect.bottom - clientRect.top); HWND insertAfter = window->win32.hWnd; for_list(&window->win32.layers, layer, mp_layer, listElt) { - mp_rect frame = layer->userFrame; - - int minX = Clamp(frame.x, 0, parentWidth); - int maxX = Clamp(frame.x + frame.w, 0, parentWidth); - int minY = Clamp(frame.y, 0, parentHeight); - int maxY = Clamp(frame.y + frame.h, 0, parentHeight); - SetWindowPos(layer->hWnd, insertAfter, - point.x + minX * scale.x, - point.y + minY * scale.y, - (maxX - minX) * scale.x, - (maxY - minY) * scale.y, + point.x, + point.y, + clientWidth, + clientHeight, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER); insertAfter = layer->hWnd; @@ -967,14 +924,17 @@ vec2 mg_win32_surface_contents_scaling(mg_surface_data* surface) return(contentsScaling); } -mp_rect mg_win32_surface_get_frame(mg_surface_data* surface) +vec2 mg_win32_surface_get_size(mg_surface_data* surface) { - return(surface->layer.userFrame); -} - -void mg_win32_surface_set_frame(mg_surface_data* surface, mp_rect frame) -{ - mg_win32_layer_set_frame(&surface->layer, frame); + vec2 size = {0}; + RECT rect; + if(GetClientRect(surface->layer.hWnd, &rect)) + { + u32 dpi = GetDpiForWindow(surface->layer.hWnd); + f32 scale = (float)dpi/96.; + size = (vec2){(rect.right - rect.left)/scale, (rect.bottom - rect.top)/scale}; + } + return(size); } bool mg_win32_surface_get_hidden(mg_surface_data* surface) @@ -1039,8 +999,7 @@ LRESULT LayerWinProc(HWND windowHandle, UINT message, WPARAM wParam, LPARAM lPar void mg_surface_init_for_window(mg_surface_data* surface, mp_window_data* window) { surface->contentsScaling = mg_win32_surface_contents_scaling; - surface->getFrame = mg_win32_surface_get_frame; - surface->setFrame = mg_win32_surface_set_frame; + surface->getSize = mg_win32_surface_get_size; surface->getHidden = mg_win32_surface_get_hidden; surface->setHidden = mg_win32_surface_set_hidden; surface->nativeLayer = mg_win32_surface_native_layer; @@ -1059,17 +1018,12 @@ void mg_surface_init_for_window(mg_surface_data* surface, mp_window_data* window POINT point = {0}; ClientToScreen(window->win32.hWnd, &point); - int width = parentRect.right - parentRect.left; - int height = parentRect.bottom - parentRect.top; - - u32 dpi = GetDpiForWindow(window->win32.hWnd); - vec2 scale = (vec2){(float)dpi/96., (float)dpi/96.}; - - surface->layer.userFrame = (mp_rect){0, 0, width / scale.x, height / scale.y}; + int clientWidth = parentRect.right - parentRect.left; + int clientHeight = parentRect.bottom - parentRect.top; surface->layer.hWnd = CreateWindow("layer_window_class", "layer", WS_POPUP | WS_VISIBLE, - point.x, point.y, width, height, + point.x, point.y, clientWidth, clientHeight, window->win32.hWnd, 0, layerWindowClass.hInstance, @@ -1097,8 +1051,7 @@ void mg_surface_init_for_window(mg_surface_data* surface, mp_window_data* window void mg_surface_init_remote(mg_surface_data* surface, u32 width, u32 height) { surface->contentsScaling = mg_win32_surface_contents_scaling; - surface->getFrame = mg_win32_surface_get_frame; - surface->setFrame = mg_win32_surface_set_frame; + surface->getSize = mg_win32_surface_get_size; surface->getHidden = mg_win32_surface_get_hidden; surface->setHidden = mg_win32_surface_set_hidden; surface->nativeLayer = mg_win32_surface_native_layer; diff --git a/src/win32_app.h b/src/win32_app.h index 7124a88..2eb0e44 100644 --- a/src/win32_app.h +++ b/src/win32_app.h @@ -28,7 +28,6 @@ typedef struct mp_layer { mp_window_data* parent; list_elt listElt; - mp_rect userFrame; HWND hWnd; } mp_layer;