/** * @file lv_ctr_disp.c * */ #if 1 /********************* * INCLUDES *********************/ #include "lv_ctr_disp.h" #include #include <3ds.h> #include #include /********************* * DEFINES *********************/ #define BOTTOM_DISP_HOR_RES 320 #define BOTTOM_DISP_VER_RES 240 #define BOTTOM_TEX_HOR_RES 512 #define BOTTOM_TEX_VER_RES 256 #define BYTE_PER_PIXEL (LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_ARGB8888)) /********************** * TYPEDEFS **********************/ /********************** * STATIC PROTOTYPES **********************/ static void disp_init(void); static void disp_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map); /* Calculate nearest power of 2 for a given size */ __attribute__ ((const)) static inline u32 tex_pot(u32 x) { if (x < 32) return 32; return 1 << (32 - __builtin_clz(x - 1)); } /********************** * STATIC VARIABLES **********************/ C3D_RenderTarget *bottom_screen; C3D_Tex tex; Tex3DS_SubTexture subt3x; /********************** * MACROS **********************/ /********************** * GLOBAL FUNCTIONS **********************/ void lv_ctr_disp_init(void) { /*------------------------- * Initialize your display * -----------------------*/ disp_init(); /*------------------------------------ * Create a display and set a flush_cb * -----------------------------------*/ lv_display_t * bottom_disp = lv_display_create(BOTTOM_DISP_HOR_RES, BOTTOM_DISP_VER_RES); lv_display_set_flush_cb(bottom_disp, disp_flush); /* Two buffers for double buffering. */ #define BOTTOM_TEX_STRIDE (BOTTOM_TEX_HOR_RES * BYTE_PER_PIXEL) LV_ATTRIBUTE_MEM_ALIGN static uint8_t buf_1[BOTTOM_TEX_STRIDE * BOTTOM_DISP_VER_RES]; LV_ATTRIBUTE_MEM_ALIGN static uint8_t buf_2[BOTTOM_TEX_STRIDE * BOTTOM_DISP_VER_RES]; lv_display_set_buffers_with_stride(bottom_disp, buf_1, buf_2, sizeof(buf_1), BOTTOM_TEX_STRIDE, LV_DISPLAY_RENDER_MODE_FULL); } /********************** * STATIC FUNCTIONS **********************/ /*Initialize your display and the required peripherals.*/ static void disp_init(void) { gfxInitDefault(); ptmuInit(); C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); C2D_Init(C2D_DEFAULT_MAX_OBJECTS); C2D_Prepare(); bottom_screen = C2D_CreateScreenTarget(GFX_BOTTOM, GFX_LEFT); if(0 == C3D_TexInit(&tex, BOTTOM_TEX_HOR_RES, BOTTOM_TEX_VER_RES, GPU_RGB8)) puts("Could not create main texture."); memset(tex.data, 0, tex.size); tex.border = 0xFFFFFFFF; C3D_TexSetWrap(&tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER); subt3x.width = BOTTOM_DISP_HOR_RES; subt3x.height = BOTTOM_DISP_VER_RES; subt3x.left = 0.0f; subt3x.top = 1.0f; subt3x.right = (BOTTOM_DISP_HOR_RES/(float)tex.width); subt3x.bottom = (1.0f - BOTTOM_DISP_VER_RES/(float)tex.height); C3D_TexSetFilter(&tex, GPU_NEAREST, GPU_NEAREST); } volatile bool disp_flush_enabled = true; /* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL */ void disp_enable_update(void) { disp_flush_enabled = true; } /* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL */ void disp_disable_update(void) { disp_flush_enabled = false; } /*Flush the content of the internal buffer the specific area on the display. *`px_map` contains the rendered image as raw pixel map and it should be copied to `area` on the display. *You can use DMA or any hardware acceleration to do this operation in the background but *'lv_display_flush_ready()' has to be called when it's finished.*/ static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map) { if (lv_display_flush_is_last(disp_drv)) { GSPGPU_FlushDataCache(px_map, tex.width * tex.height * 4); u32 dim = GX_BUFFER_DIM(tex.width, tex.height); C3D_SyncDisplayTransfer((u32 *)px_map, dim, (u32*)tex.data, dim, (GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)) ); // start frame, clear targets C3D_FrameBegin(C3D_FRAME_SYNCDRAW); C2D_TargetClear(bottom_screen, C2D_Color32f(0, 0, 0, 1)); C2D_SceneBegin(bottom_screen); C2D_Image img = { &tex, &subt3x }; C2D_DrawImageAt(img, 0, 0, 0.6f, NULL, 1.0f, 1.0f); C3D_FrameEnd(0); } lv_display_flush_ready(disp_drv); } #else /*Enable this file at the top*/ /*This dummy typedef exists purely to silence -Wpedantic.*/ typedef int keep_pedantic_happy; #endif