diff --git a/examples/sokol/main.c b/examples/sokol/main.c index 0da7659..4700cb8 100644 --- a/examples/sokol/main.c +++ b/examples/sokol/main.c @@ -40,7 +40,7 @@ static void app_init(void) } } - sokol_gfx_init(TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 1, 1); + sokol_gfx_init(TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 1, 1, false, false); } static tic80_input tic_input; diff --git a/src/system/sokol.c b/src/system/sokol.c index 39e070f..d5ff6f2 100644 --- a/src/system/sokol.c +++ b/src/system/sokol.c @@ -131,7 +131,7 @@ static System systemInterface = static void app_init(void) { - sokol_gfx_init(TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 1, 1); + sokol_gfx_init(TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 1, 1, false, true); platform.audio.samples = calloc(sizeof platform.audio.samples[0], saudio_sample_rate() / TIC_FRAMERATE * TIC_STEREO_CHANNLES); } @@ -306,38 +306,6 @@ static void handleKeydown(sapp_keycode keycode, bool down) } } -static void calcViewportSize(tic_rect* rect) -{ - enum{Width = TIC80_WIDTH, Height = TIC80_HEIGHT}; - - if (rect->w * Height < rect->h * Width) - { - s32 discreteWidth = rect->w;// - rect->w % Width; - s32 discreteHeight = Height * discreteWidth / Width; - - rect->x = (rect->w - discreteWidth) / 2; - - rect->y = rect->w > rect->h - ? (rect->h - discreteHeight) / 2 - : OFFSET_TOP*discreteWidth/Width; - - rect->w = discreteWidth; - rect->h = discreteHeight; - - } - else - { - s32 discreteHeight = rect->h;// - rect->h % Height; - s32 discreteWidth = Width * discreteHeight / Height; - - rect->x = (rect->w - discreteWidth) / 2; - rect->y = (rect->h - discreteHeight) / 2; - - rect->w = discreteWidth; - rect->h = discreteHeight; - } -} - static void app_input(const sapp_event* event) { tic80_input* input = &platform.studio->tic->ram.input; diff --git a/src/system/sokol.h b/src/system/sokol.h index 5675dab..9d1944f 100644 --- a/src/system/sokol.h +++ b/src/system/sokol.h @@ -7,5 +7,5 @@ #include -void sokol_gfx_init(int w, int h, int sx, int sy); +void sokol_gfx_init(int w, int h, int sx, int sy, bool integer_scale, bool portrait_top_align); void sokol_gfx_draw(const uint32_t* ptr); diff --git a/src/system/sokol_gfx.c b/src/system/sokol_gfx.c index 6da366a..9811de2 100644 --- a/src/system/sokol_gfx.c +++ b/src/system/sokol_gfx.c @@ -2,13 +2,16 @@ static struct { - sg_draw_state upscale_draw_state; - sg_pass upscale_pass; - sg_draw_state draw_state; - int fb_width; - int fb_height; - int fb_aspect_scale_x; - int fb_aspect_scale_y; + sg_draw_state upscale_draw_state; + sg_pass upscale_pass; + sg_draw_state draw_state; + int fb_width; + int fb_height; + int fb_aspect_scale_x; + int fb_aspect_scale_y; + + bool integer_scale; + bool portrait_top_align; } sokol_gfx; #if defined(SOKOL_GLCORE33) @@ -96,11 +99,14 @@ static const char* gfx_fs_src = "}\n"; #endif -void sokol_gfx_init(int w, int h, int sx, int sy) { +void sokol_gfx_init(int w, int h, int sx, int sy, bool integer_scale, bool portrait_top_align) { sokol_gfx.fb_width = w; sokol_gfx.fb_height = h; sokol_gfx.fb_aspect_scale_x = sx; sokol_gfx.fb_aspect_scale_y = sy; + sokol_gfx.integer_scale = integer_scale; + sokol_gfx.portrait_top_align = portrait_top_align; + sg_setup(&(sg_desc){ .mtl_device = sapp_metal_get_device(), .mtl_renderpass_descriptor_cb = sapp_metal_get_renderpass_descriptor, @@ -193,28 +199,33 @@ static const sg_pass_action gfx_draw_pass_action = { }; static void apply_viewport(void) { - const int canvas_width = sapp_width(); - const int canvas_height = sapp_height(); - const float canvas_aspect = (float)canvas_width / (float)canvas_height; - const float fb_aspect = (float)(sokol_gfx.fb_width*sokol_gfx.fb_aspect_scale_x) / (float)(sokol_gfx.fb_height*sokol_gfx.fb_aspect_scale_y); - int vp_x, vp_y, vp_w, vp_h; - if (fb_aspect < canvas_aspect) { - vp_y = 0; - vp_h = canvas_height; - vp_w = (int) (canvas_height * fb_aspect); - vp_x = (canvas_width - vp_w) / 2; - } - else { - vp_x = 0; - vp_w = canvas_width; - vp_h = (int) (canvas_width / fb_aspect); + int vp_x = 0, vp_y = 0, vp_w = sapp_width(), vp_h = sapp_height(); - // align top - vp_y = 0; + if (vp_w * sokol_gfx.fb_height < vp_h * sokol_gfx.fb_width) + { + int discreteWidth = vp_w - (sokol_gfx.integer_scale ? vp_w % sokol_gfx.fb_width : 0); + int discreteHeight = sokol_gfx.fb_height * discreteWidth / sokol_gfx.fb_width; - // align vcenter - //vp_y = (canvas_height - vp_h) / 2; + vp_x = (vp_w - discreteWidth) / 2; + vp_y = sokol_gfx.portrait_top_align && vp_w < vp_h + ? 0 + : (vp_h - discreteHeight) / 2; + + vp_w = discreteWidth; + vp_h = discreteHeight; } + else + { + int discreteHeight = vp_h - (sokol_gfx.integer_scale ? vp_h % sokol_gfx.fb_height : 0); + int discreteWidth = sokol_gfx.fb_width * discreteHeight / sokol_gfx.fb_height; + + vp_x = (vp_w - discreteWidth) / 2; + vp_y = (vp_h - discreteHeight) / 2; + + vp_w = discreteWidth; + vp_h = discreteHeight; + } + sg_apply_viewport(vp_x, vp_y, vp_w, vp_h, true); }