diff --git a/nx/include/switch/gfx/gfx.h b/nx/include/switch/gfx/gfx.h index 7b5bb127..c4cdba03 100644 --- a/nx/include/switch/gfx/gfx.h +++ b/nx/include/switch/gfx/gfx.h @@ -2,10 +2,35 @@ void gfxInitDefault(void); void gfxExit(void); +/// Note that "framebuffer" here is technically windowbuffer. + void gfxWaitForVsync(); void gfxSwapBuffers(); u8* gfxGetFramebuffer(u32* width, u32* height); void gfxSetDoubleBuffering(bool doubleBuffering); void gfxFlushBuffers(void); -u32 gfxGetFramebufferDisplayOffset(u32 x, u32 y); +//Do not use this for getting the framebuffer width/height, use gfxGetFramebuffer for getting that. +Result gfxGetDisplayResolution(u64 *width, u64 *height); + +/// Use this to get the pixel-offset in the framebuffer. Returned value is in pixels, not bytes. +/// This implements tegra blocklinear, with hard-coded constants etc. +static inline u32 gfxGetFramebufferDisplayOffset(u32 x, u32 y) { + u32 width=0, height=0; + u32 tilepos, tmp_pos; + + gfxGetFramebuffer(&width, &height); + + if (x >= width) x = width-1; + if (y >= height) y = height-1; + + y = height-1-y; + + tilepos = ((y & 127) / 16) + (x/16*8) + ((y/16/8)*(width/16*8)); + tilepos = tilepos*16*16 * 4; + + tmp_pos = ((y%16)/8)*512 + ((x%16)/8)*256 + ((y%8)/2)*64 + ((x%8)/4)*32 + (y%2)*16 + (x%4)*4;//This line is a modified version of code from the Tegra X1 datasheet. + + return (tilepos + tmp_pos) / 4; +} + diff --git a/nx/include/switch/services/vi.h b/nx/include/switch/services/vi.h index ea7448c9..d6cd2dfc 100644 --- a/nx/include/switch/services/vi.h +++ b/nx/include/switch/services/vi.h @@ -44,4 +44,5 @@ Result viCloseLayer(viLayer *layer); /// See viScalingMode. Result viSetLayerScalingMode(viLayer *layer, u32 ScalingMode); +Result viGetDisplayResolution(viDisplay *display, u64 *width, u64 *height); Result viGetDisplayVsyncEvent(viDisplay *display, Handle *handle_out); diff --git a/nx/source/gfx/gfx.c b/nx/source/gfx/gfx.c index e57cade8..f11e9fed 100644 --- a/nx/source/gfx/gfx.c +++ b/nx/source/gfx/gfx.c @@ -257,23 +257,7 @@ void gfxFlushBuffers(void) { armDCacheFlush(&g_gfxFramebuf[g_gfxCurrentBuffer*g_nvgfx_singleframebuf_size], g_nvgfx_singleframebuf_size); } -//This implements tegra blocklinear, with hard-coded constants etc. -u32 gfxGetFramebufferDisplayOffset(u32 x, u32 y) { - u32 width=0, height=0; - u32 tilepos, tmp_pos; - - gfxGetFramebuffer(&width, &height); - - if (x >= width) x = width-1; - if (y >= height) y = height-1; - - y = height-1-y; - - tilepos = ((y & 127) / 16) + (x/16*8) + ((y/16/8)*(width/16*8)); - tilepos = tilepos*16*16 * 4; - - tmp_pos = ((y%16)/8)*512 + ((x%16)/8)*256 + ((y%8)/2)*64 + ((x%8)/4)*32 + (y%2)*16 + (x%4)*4;//This line is a modified version of code from the Tegra X1 datasheet. - - return (tilepos + tmp_pos) / 4; +Result gfxGetDisplayResolution(u64 *width, u64 *height) { + return viGetDisplayResolution(&g_gfxDisplay, width, height); } diff --git a/nx/source/services/vi.c b/nx/source/services/vi.c index a2c88eda..cf4f0ca6 100644 --- a/nx/source/services/vi.c +++ b/nx/source/services/vi.c @@ -440,6 +440,46 @@ Result viSetLayerScalingMode(viLayer *layer, u32 ScalingMode) { return rc; } +Result viGetDisplayResolution(viDisplay *display, u64 *width, u64 *height) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 DisplayId; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1102; + raw->DisplayId = display->DisplayId; + + Result rc = ipcDispatch(g_viIApplicationDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcCommandResponse r; + ipcParseResponse(&r); + + struct { + u64 magic; + u64 result; + u64 width; + u64 height; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (width) *width = resp->width; + if (height) *height = resp->height; + } + } + + return rc; +} + Result viGetDisplayVsyncEvent(viDisplay *display, Handle *handle_out) { IpcCommand c; ipcInitialize(&c);