From 0ea76cf3ed6d8485758d25032dfc3b6395af13f5 Mon Sep 17 00:00:00 2001 From: fincs Date: Mon, 17 Dec 2018 20:18:02 +0100 Subject: [PATCH] Replace usage of old gfx API with new NWindow/Framebuffer API. Clean up some of the examples that used mixed console + custom sw rendering. --- applet/lockexit/source/main.c | 2 +- applet/recording/source/main.c | 56 +++++---- exception-handler/source/main.c | 2 +- graphics/shared_font/source/main.c | 189 ++++++++++++++++------------ graphics/simplegfx/source/main.c | 87 +++++++------ hid/irsensor/source/main.c | 159 +++++++++++------------ templates/application/source/main.c | 2 +- usb/usbhs/source/main.c | 2 +- 8 files changed, 278 insertions(+), 221 deletions(-) diff --git a/applet/lockexit/source/main.c b/applet/lockexit/source/main.c index b876996..cad7a63 100644 --- a/applet/lockexit/source/main.c +++ b/applet/lockexit/source/main.c @@ -17,7 +17,7 @@ int main(int argc, char* argv[]) // This example uses a text console, as a simple way to output text to the screen. // If you want to write a software-rendered graphics application, - // take a look at the graphics/simplegfx example, which uses the libnx gfx API instead. + // take a look at the graphics/simplegfx example, which uses the libnx Framebuffer API instead. // If on the other hand you want to write an OpenGL based application, // take a look at the graphics/opengl set of examples, which uses EGL instead. consoleInit(NULL); diff --git a/applet/recording/source/main.c b/applet/recording/source/main.c index b6b45f0..ce8af12 100644 --- a/applet/recording/source/main.c +++ b/applet/recording/source/main.c @@ -1,18 +1,35 @@ -#include +// Include the most common headers from the C standard library #include +#include +#include + +// Include the main libnx system header, for Switch development #include //See also libnx applet.h. See applet.h for the requirements for using this. +// Define the desired framebuffer resolution (here we set it to 720p). +#define FB_WIDTH 1280 +#define FB_HEIGHT 720 + +// Remove above and uncomment below for 1080p +//#define FB_WIDTH 1920 +//#define FB_HEIGHT 1080 + int main(int argc, char **argv) { - u32* framebuf; - u32 cnt=0; + // Retrieve the default window + NWindow* win = nwindowGetDefault(); - gfxInitDefault(); + // Create a linear double-buffered framebuffer + Framebuffer fb; + framebufferCreate(&fb, win, FB_WIDTH, FB_HEIGHT, PIXEL_FORMAT_RGBA_8888, 2); + framebufferMakeLinear(&fb); appletInitializeGamePlayRecording();//Normally this is only recording func you need to call. + u32 cnt = 0; + while(appletMainLoop()) { //Scan all the inputs. This should be done once for each frame @@ -30,34 +47,29 @@ int main(int argc, char **argv) appletSetGamePlayRecordingState(1);//Enable recording. } - u32 width, height; - u32 pos; - framebuf = (u32*) gfxGetFramebuffer((u32*)&width, (u32*)&height); + // Retrieve the framebuffer + u32 stride; + u32* framebuf = (u32*) framebufferBegin(&fb, &stride); - if(cnt==60) - { - cnt=0; - } + if (cnt != 60) + cnt ++; else - { - cnt++; - } + cnt = 0; - //Each pixel is 4-bytes due to RGBA8888. - u32 x, y; - for (y=0; y #include #include +#include #include #include @@ -8,6 +9,10 @@ //See also libnx pl.h. +// Define the desired framebuffer resolution (here we set it to 720p). +#define FB_WIDTH 1280 +#define FB_HEIGHT 720 + //This requires the switch-freetype package. //Freetype code here is based on the example code from freetype docs. @@ -38,7 +43,7 @@ void draw_glyph(FT_Bitmap* bitmap, u32* framebuf, u32 x, u32 y) //Note that this doesn't handle {tmpx > width}, etc. //str is UTF-8. -void draw_text(FT_Face face, u32* framebuf, u32 x, u32 y, const uint8_t* str) +void draw_text(FT_Face face, u32* framebuf, u32 x, u32 y, const char* str) { u32 tmpx = x; FT_Error ret=0; @@ -46,13 +51,13 @@ void draw_text(FT_Face face, u32* framebuf, u32 x, u32 y, const uint8_t* str) FT_GlyphSlot slot = face->glyph; u32 i; - u32 str_size = strlen((const char*)str); + u32 str_size = strlen(str); uint32_t tmpchar; ssize_t unitcount=0; for (i = 0; i < str_size; ) { - unitcount = decode_utf8 (&tmpchar, &str[i]); + unitcount = decode_utf8 (&tmpchar, (const uint8_t*)&str[i]); if (unitcount <= 0) break; i+= unitcount; @@ -86,84 +91,112 @@ void draw_text(FT_Face face, u32* framebuf, u32 x, u32 y, const uint8_t* str) } } +__attribute__((format(printf, 1, 2))) +static int error_screen(const char* fmt, ...) +{ + consoleInit(NULL); + va_list va; + va_start(va, fmt); + vprintf(fmt, va); + va_end(va); + printf("Press PLUS to exit\n"); + while (appletMainLoop()) + { + hidScanInput(); + if (hidKeysDown(CONTROLLER_P1_AUTO) & KEY_PLUS) + break; + consoleUpdate(NULL); + } + consoleExit(NULL); + return EXIT_FAILURE; +} + +static u64 getSystemLanguage(void) +{ + Result rc; + u64 code = 0; + + rc = setInitialize(); + if (R_SUCCEEDED(rc)) { + rc = setGetSystemLanguage(&code); + setExit(); + } + + return R_SUCCEEDED(rc) ? code : 0; +} + +// LanguageCode is only needed with shared-font when using plGetSharedFont. +static u64 LanguageCode; + +void userAppInit(void) +{ + Result rc; + + rc = plInitialize(); + if (R_FAILED(rc)) + fatalSimple(rc); + + LanguageCode = getSystemLanguage(); +} + +void userAppExit(void) +{ + plExit(); +} + int main(int argc, char **argv) { Result rc=0; - u32* framebuf; + FT_Error ret=0; - u64 LanguageCode=0; - PlFontData font; + //Use this when using multiple shared-fonts. + /* PlFontData fonts[PlSharedFontType_Total]; size_t total_fonts=0; - FT_Error ret=0, libret=1, faceret=1; - FT_Library library; - FT_Face face; - - gfxInitDefault(); - consoleInit(NULL); + rc = plGetSharedFont(LanguageCode, fonts, PlSharedFontType_Total, &total_fonts); + if (R_FAILED(rc)) + return error_screen("plGetSharedFont() failed: 0x%x\n", rc); + */ - rc = setInitialize();//Only needed with shared-font when using plGetSharedFont. - if (R_SUCCEEDED(rc)) rc = setGetSystemLanguage(&LanguageCode); - setExit(); - - if (R_FAILED(rc)) printf("Failed to get system-language: 0x%x\n", rc); + // Use this when you want to use specific shared-font(s). Since this example only uses 1 font, only the font loaded by this will be used. + PlFontData font; + rc = plGetSharedFontByType(&font, PlSharedFontType_Standard); + if (R_FAILED(rc)) + return error_screen("plGetSharedFontByType() failed: 0x%x\n", rc); - if (R_SUCCEEDED(rc)) - { - rc = plInitialize(); - if (R_FAILED(rc)) printf("plInitialize() failed: 0x%x\n", rc); + FT_Library library; + ret = FT_Init_FreeType(&library); + if (ret) + return error_screen("FT_Init_FreeType() failed: %d\n", ret); - if (R_SUCCEEDED(rc)) - { - //Use this when using multiple shared-fonts. - rc = plGetSharedFont(LanguageCode, fonts, PlSharedFontType_Total, &total_fonts); - if (R_FAILED(rc)) printf("plGetSharedFont() failed: 0x%x\n", rc); - - //Use this when you want to use specific shared-font(s). Since this example only uses 1 font, only the font loaded by this will be used. - rc = plGetSharedFontByType(&font, PlSharedFontType_Standard); - if (R_FAILED(rc)) printf("plGetSharedFontByType() failed: 0x%x\n", rc); - - if (R_SUCCEEDED(rc)) - { - ret = FT_Init_FreeType(&library); - libret = ret; - if (ret) printf("FT_Init_FreeType() failed: %d\n", ret); - - if (ret==0) - { - ret = FT_New_Memory_Face( library, - font.address, /* first byte in memory */ - font.size, /* size in bytes */ - 0, /* face_index */ - &face); - - faceret = ret; - if (ret) printf("FT_New_Memory_Face() failed: %d\n", ret); - - if (ret==0) - { - ret = FT_Set_Char_Size( - face, /* handle to face object */ - 0, /* char_width in 1/64th of points */ - 8*64, /* char_height in 1/64th of points */ - 300, /* horizontal device resolution */ - 300); /* vertical device resolution */ - - if (ret) printf("FT_Set_Char_Size() failed: %d\n", ret); - } - } - } - } + FT_Face face; + ret = FT_New_Memory_Face( library, + font.address, /* first byte in memory */ + font.size, /* size in bytes */ + 0, /* face_index */ + &face); + if (ret) { + FT_Done_FreeType(library); + return error_screen("FT_New_Memory_Face() failed: %d\n", ret); } - if (R_SUCCEEDED(rc) && ret==0) - { - //Switch to using regular framebuffer. - consoleClear(); - gfxSetMode(GfxMode_LinearDouble); + ret = FT_Set_Char_Size( + face, /* handle to face object */ + 0, /* char_width in 1/64th of points */ + 24*64, /* char_height in 1/64th of points */ + 96, /* horizontal device resolution */ + 96); /* vertical device resolution */ + if (ret) { + FT_Done_Face(face); + FT_Done_FreeType(library); + return error_screen("FT_Set_Char_Size() failed: %d\n", ret); } - while(appletMainLoop()) + Framebuffer fb; + framebufferCreate(&fb, nwindowGetDefault(), FB_WIDTH, FB_HEIGHT, PIXEL_FORMAT_RGBA_8888, 2); + framebufferMakeLinear(&fb); + + while (appletMainLoop()) { //Scan all the inputs. This should be done once for each frame hidScanInput(); @@ -173,20 +206,18 @@ int main(int argc, char **argv) if (kDown & KEY_PLUS) break; // break in order to return to hbmenu - framebuf = (u32*) gfxGetFramebuffer(&framebuf_width, NULL); - - memset(framebuf, 0, gfxGetFramebufferSize()); + u32 stride; + u32* framebuf = (u32*)framebufferBegin(&fb, &stride); + framebuf_width = stride / sizeof(u32); - if (R_SUCCEEDED(rc) && ret==0) draw_text(face, framebuf, 64, 64, (const uint8_t*)"The quick brown fox jumps over the lazy dog. ファイル\ntest Test"); + memset(framebuf, 0, stride*FB_HEIGHT); + draw_text(face, framebuf, 64, 64, u8"The quick brown fox jumps over the lazy dog. ファイル\ntest Test"); - gfxFlushBuffers(); - gfxSwapBuffers(); + framebufferEnd(&fb); } - if (faceret==0) FT_Done_Face(face); - if (libret==0) FT_Done_FreeType(library); - - plExit(); - gfxExit(); + framebufferClose(&fb); + FT_Done_Face(face); + FT_Done_FreeType(library); return 0; } diff --git a/graphics/simplegfx/source/main.c b/graphics/simplegfx/source/main.c index ca1ab91..c879ace 100644 --- a/graphics/simplegfx/source/main.c +++ b/graphics/simplegfx/source/main.c @@ -1,71 +1,82 @@ -#include +// Include the most common headers from the C standard library #include +#include +#include + +// Include the main libnx system header, for Switch development #include #ifdef DISPLAY_IMAGE #include "image_bin.h"//Your own raw RGB888 1280x720 image at "data/image.bin" is required. #endif -//See also libnx gfx.h. +// See also libnx display/framebuffer.h. + +// Define the desired framebuffer resolution (here we set it to 720p). +#define FB_WIDTH 1280 +#define FB_HEIGHT 720 -int main(int argc, char **argv) +// Remove above and uncomment below for 1080p +//#define FB_WIDTH 1920 +//#define FB_HEIGHT 1080 + +// Main program entrypoint +int main(int argc, char* argv[]) { - u32* framebuf; - u32 cnt=0; - #ifdef DISPLAY_IMAGE - u8* imageptr = (u8*)image_bin; - #endif + // Retrieve the default window + NWindow* win = nwindowGetDefault(); - //Enable max-1080p support. Remove for 720p-only resolution. - //gfxInitResolutionDefault(); + // Create a linear double-buffered framebuffer + Framebuffer fb; + framebufferCreate(&fb, win, FB_WIDTH, FB_HEIGHT, PIXEL_FORMAT_RGBA_8888, 2); + framebufferMakeLinear(&fb); - gfxInitDefault(); +#ifdef DISPLAY_IMAGE + u8* imageptr = (u8*)image_bin; +#endif - //Set current resolution automatically depending on current/changed OperationMode. Only use this when using gfxInitResolution*(). - //gfxConfigureAutoResolutionDefault(true); + u32 cnt = 0; - while(appletMainLoop()) + // Main loop + while (appletMainLoop()) { - //Scan all the inputs. This should be done once for each frame + // Scan all the inputs. This should be done once for each frame hidScanInput(); - //hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame) + // hidKeysDown returns information about which buttons have been + // just pressed in this frame compared to the previous one u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); - if (kDown & KEY_PLUS) break; // break in order to return to hbmenu + if (kDown & KEY_PLUS) + break; // break in order to return to hbmenu - u32 width, height; - u32 pos; - framebuf = (u32*) gfxGetFramebuffer((u32*)&width, (u32*)&height); + // Retrieve the framebuffer + u32 stride; + u32* framebuf = (u32*) framebufferBegin(&fb, &stride); - if(cnt==60) - { - cnt=0; - } + if (cnt != 60) + cnt ++; else - { - cnt++; - } + cnt = 0; - //Each pixel is 4-bytes due to RGBA8888. - u32 x, y; - for (y=0; y +#include #include -#include +#include #include //Joy-con IR-sensor example, displays the image from the IR camera. //The Joy-con must be detached from the system. -int main(int argc, char **argv) +// Define the desired framebuffer resolution (here we set it to 720p). +#define FB_WIDTH 1280 +#define FB_HEIGHT 720 + +void userAppInit(void) { - Result rc=0; - Result rc2=0; - u32 irhandle=0; - IrsImageTransferProcessorConfig config; - IrsImageTransferProcessorState state; - size_t ir_buffer_size = 0x12c00; - u8 *ir_buffer = NULL; + Result rc; - u32 width, height; - u32 ir_width, ir_height; - u32 pos, pos2=0; - u32* framebuf; + rc = irsInitialize(); + if (R_FAILED(rc)) + fatalSimple(rc); +} - gfxInitDefault(); +void userAppExit(void) +{ + irsExit(); +} - //Initialize console. Using NULL as the second argument tells the console library to use the internal console structure as current one. +__attribute__((format(printf, 1, 2))) +static int error_screen(const char* fmt, ...) +{ consoleInit(NULL); - - ir_buffer = (u8*)malloc(ir_buffer_size); - if (ir_buffer==NULL) - { - rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); - printf("Failed to allocate memory for ir_buffer.\n"); - } - else + va_list va; + va_start(va, fmt); + vprintf(fmt, va); + va_end(va); + printf("Press PLUS to exit\n"); + while (appletMainLoop()) { - memset(ir_buffer, 0, ir_buffer_size); + hidScanInput(); + if (hidKeysDown(CONTROLLER_P1_AUTO) & KEY_PLUS) + break; + consoleUpdate(NULL); } + consoleExit(NULL); + return EXIT_FAILURE; +} - if (R_SUCCEEDED(rc)) - { - rc = irsInitialize(); - printf("irsInitialize() returned 0x%x\n", rc); - } +int main(int argc, char **argv) +{ + Result rc=0; - if (R_SUCCEEDED(rc)) + const size_t ir_buffer_size = 0x12c00; + u8 *ir_buffer = NULL; + ir_buffer = (u8*)malloc(ir_buffer_size); + if (!ir_buffer) { - rc = irsActivateIrsensor(1); - printf("irsActivateIrsensor() returned 0x%x\n", rc); + rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory); + return error_screen("Failed to allocate memory for ir_buffer.\n"); } - if (R_SUCCEEDED(rc)) - { - rc = irsGetIrCameraHandle(&irhandle, CONTROLLER_PLAYER_1); - //If you want to use handheld-mode/non-CONTROLLER_PLAYER_* for irsensor you have to set irhandle directly, for example: irhandle = CONTROLLER_HANDHELD; - printf("irsGetIrCameraHandle() returned 0x%x\n", rc); - } + memset(ir_buffer, 0, ir_buffer_size); + rc = irsActivateIrsensor(1); + if (R_FAILED(rc)) + return error_screen("irsActivateIrsensor() returned 0x%x\n", rc); - if (R_SUCCEEDED(rc)) - { - irsGetDefaultImageTransferProcessorConfig(&config); - rc = irsRunImageTransferProcessor(irhandle, &config, 0x100000); - printf("irsRunImageTransferProcessor() returned 0x%x\n", rc); - } + //If you want to use handheld-mode/non-CONTROLLER_PLAYER_* for irsensor you have to set irhandle directly, for example: irhandle = CONTROLLER_HANDHELD; + u32 irhandle=0; + rc = irsGetIrCameraHandle(&irhandle, CONTROLLER_PLAYER_1); + if (R_FAILED(rc)) + return error_screen("irsGetIrCameraHandle() returned 0x%x\n", rc); - if (R_SUCCEEDED(rc)) - { - //Switch to using regular framebuffer. - consoleClear(); - gfxSetMode(GfxMode_LinearDouble); - } + IrsImageTransferProcessorConfig config; + irsGetDefaultImageTransferProcessorConfig(&config); + rc = irsRunImageTransferProcessor(irhandle, &config, 0x100000); + if (R_FAILED(rc)) + return error_screen("irsRunImageTransferProcessor() returned 0x%x\n", rc); + + Framebuffer fb; + framebufferCreate(&fb, nwindowGetDefault(), FB_WIDTH, FB_HEIGHT, PIXEL_FORMAT_RGBA_8888, 2); + framebufferMakeLinear(&fb); - while(appletMainLoop()) + while (appletMainLoop()) { //Scan all the inputs. This should be done once for each frame hidScanInput(); @@ -81,46 +90,40 @@ int main(int argc, char **argv) if (kDown & KEY_PLUS) break; // break in order to return to hbmenu + //Note that the image is updated every few seconds. Likewise, it takes a few seconds for the initial image to become available. + //This will return an error when no image is available yet. + IrsImageTransferProcessorState state; + rc = irsGetImageTransferProcessorState(irhandle, ir_buffer, ir_buffer_size, &state); + + u32 stride; + u32* framebuf = (u32*)framebufferBegin(&fb, &stride); + if (R_SUCCEEDED(rc)) { - framebuf = (u32*) gfxGetFramebuffer((u32*)&width, (u32*)&height); + memset(framebuf, 0, stride*FB_HEIGHT); - //Note that the image is updated every few seconds. Likewise, it takes a few seconds for the initial image to become available. - //This will return an error when no image is available yet. - rc2 = irsGetImageTransferProcessorState(irhandle, ir_buffer, ir_buffer_size, &state); + //IR image width/height with the default config. + //The image is grayscale (1 byte per pixel / 8bits, with 1 color-component). + const u32 ir_width = 240; + const u32 ir_height = 320; - if (R_SUCCEEDED(rc2)) + u32 x, y; + for (y=0; y