diff --git a/Makefile.ctr b/Makefile.ctr index 506361742f..428dc70290 100644 --- a/Makefile.ctr +++ b/Makefile.ctr @@ -44,7 +44,7 @@ endif DEFINES := ifeq ($(GRIFFIN_BUILD), 1) OBJ += griffin/griffin.o - DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_RGUI + DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_RGUI -DHAVE_XMB -DHAVE_MATERIALUI DEFINES += -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DWANT_ZLIB -DHAVE_BUILTIN_AUTOCONFIG else HAVE_MENU_COMMON = 1 @@ -65,6 +65,8 @@ else OBJ := $(filter-out $(BLACKLIST),$(OBJ)) OBJ += gfx/drivers/ctr_gfx.o + OBJ += gfx/drivers_font/ctr_font.o + OBJ += menu/drivers_display/menu_display_ctr.o OBJ += input/drivers/ctr_input.o OBJ += input/drivers_joypad/ctr_joypad.o OBJ += audio/drivers/ctr_csnd_audio.o diff --git a/ctr/ctr_debug.h b/ctr/ctr_debug.h index c8e79de9c7..f852e563af 100644 --- a/ctr/ctr_debug.h +++ b/ctr/ctr_debug.h @@ -21,5 +21,6 @@ void dump_result_value(Result val); #define DEBUG_ERROR(X) do{if(X)dump_result_value(X)}while(0) #define PRINTFPOS(X,Y) "\x1b["#X";"#Y"H" #define PRINTFPOS_STR(X,Y) "\x1b["X";"Y"H" +#define PRINTF_LINE(X) "\x1b["X";0H" #endif //_CTR_DEBUG_H__ diff --git a/gfx/common/ctr_common.h b/gfx/common/ctr_common.h index ffc9d108f0..4726d1c96f 100644 --- a/gfx/common/ctr_common.h +++ b/gfx/common/ctr_common.h @@ -1,6 +1,9 @@ #ifndef CTR_COMMON_H__ #define CTR_COMMON_H__ + +#define COLOR_ABGR(r, g, b, a) (((unsigned)(a) << 24) | ((b) << 16) | ((g) << 8) | ((r) << 0)) + #define CTR_TOP_FRAMEBUFFER_WIDTH 400 #define CTR_TOP_FRAMEBUFFER_HEIGHT 240 @@ -76,12 +79,40 @@ typedef struct ctr_video bool keep_aspect; bool should_resize; bool lcd_buttom_on; + bool msg_rendering_enabled; void* empty_framebuffer; aptHookCookie lcd_aptHook; ctr_video_mode_enum video_mode; int current_buffer_top; + + struct + { + ctr_vertex_t* buffer; + ctr_vertex_t* current; + int size; + }vertex_cache; + } ctr_video_t; +typedef struct ctr_texture +{ + int width; + int height; + enum texture_filter_type type; + void* data; +} ctr_texture_t; + +static INLINE void ctr_set_scale_vector(ctr_scale_vector_t* vec, + int viewport_width, int viewport_height, + int texture_width, int texture_height) +{ + vec->x = -2.0 / viewport_width; + vec->y = -2.0 / viewport_height; + vec->u = 1.0 / texture_width; + vec->v = -1.0 / texture_height; +} + + #endif // CTR_COMMON_H__ diff --git a/gfx/drivers/ctr_gfx.c b/gfx/drivers/ctr_gfx.c index 66808d449e..f554504e3e 100644 --- a/gfx/drivers/ctr_gfx.c +++ b/gfx/drivers/ctr_gfx.c @@ -20,6 +20,7 @@ #include <3ds.h> #include +#include #ifdef HAVE_CONFIG_H #include "../../config.h" @@ -28,11 +29,14 @@ #include "../../ctr/gpu_old.h" #include "ctr_gu.h" +#include "../../menu/menu_driver.h" + #include "../../configuration.h" #include "../../command.h" #include "../../driver.h" #include "../../retroarch.h" +#include "../../verbosity.h" #include "../../performance_counters.h" #include "../common/ctr_common.h" @@ -80,16 +84,6 @@ static INLINE void ctr_check_3D_slider(ctr_video_t* ctr) } } -static INLINE void ctr_set_scale_vector(ctr_scale_vector_t* vec, - int viewport_width, int viewport_height, - int texture_width, int texture_height) -{ - vec->x = -2.0 / viewport_width; - vec->y = -2.0 / viewport_height; - vec->u = 1.0 / texture_width; - vec->v = -1.0 / texture_height; -} - static INLINE void ctr_set_screen_coords(ctr_video_t * ctr) { if (ctr->rotation == 0) @@ -279,6 +273,7 @@ static void* ctr_init(const video_info_t* video, float refresh_rate; void* ctrinput = NULL; ctr_video_t* ctr = (ctr_video_t*)linearAlloc(sizeof(ctr_video_t)); + settings_t *settings = config_get_ptr(); if (!ctr) return NULL; @@ -292,14 +287,19 @@ static void* ctr_init(const video_info_t* video, ctr->vp.height = CTR_TOP_FRAMEBUFFER_HEIGHT; ctr->vp.full_width = CTR_TOP_FRAMEBUFFER_WIDTH; ctr->vp.full_height = CTR_TOP_FRAMEBUFFER_HEIGHT; + video_driver_set_size(&ctr->vp.width, &ctr->vp.height); ctr->drawbuffers.top.left = vramAlloc(CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * 2 * sizeof(uint32_t)); ctr->drawbuffers.top.right = (void*)((uint32_t*)ctr->drawbuffers.top.left + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT); - ctr->display_list_size = 0x400; + ctr->display_list_size = 0x10000; ctr->display_list = linearAlloc(ctr->display_list_size * sizeof(uint32_t)); GPU_Reset(NULL, ctr->display_list, ctr->display_list_size); + ctr->vertex_cache.size = 0x1000; + ctr->vertex_cache.buffer = linearAlloc(ctr->vertex_cache.size * sizeof(ctr_vertex_t)); + ctr->vertex_cache.current = ctr->vertex_cache.buffer; + ctr->rgb32 = video->rgb32; ctr->texture_width = video->input_scale * RARCH_SCALE_BASE; ctr->texture_height = video->input_scale * RARCH_SCALE_BASE; @@ -413,11 +413,23 @@ static void* ctr_init(const video_info_t* video, driver_ctl(RARCH_DRIVER_CTL_SET_REFRESH_RATE, &refresh_rate); aptHook(&ctr->lcd_aptHook, ctr_lcd_aptHook, ctr); + if (!font_driver_init_first(NULL, NULL, ctr, *settings->path.font + ? settings->path.font : NULL, settings->video.font_size, false, + FONT_DRIVER_RENDER_CTR)) + { + RARCH_ERR("Font: Failed to initialize font renderer.\n"); + return false; + } + + ctr->msg_rendering_enabled = false; + +// DEBUG_HOLD(); + return ctr; } static bool ctr_frame(void* data, const void* frame, - unsigned width, unsigned height, + unsigned width, unsigned height, uint64_t frame_count, unsigned pitch, const char* msg) { @@ -677,7 +689,6 @@ static bool ctr_frame(void* data, const void* frame, if (ctr->menu_texture_enable) { - GSPGPU_FlushDataCache(ctr->menu.texture_linear, ctr->menu.texture_width * ctr->menu.texture_height * sizeof(uint16_t)); @@ -706,8 +717,20 @@ static bool ctr_frame(void* data, const void* frame, CTR_TOP_FRAMEBUFFER_WIDTH); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); } + + ctr->msg_rendering_enabled = true; + menu_driver_ctl(RARCH_MENU_CTL_FRAME, NULL); + ctr->msg_rendering_enabled = false; + } + if (font_driver_has_render_msg() && msg) + font_driver_render_msg(NULL, msg, NULL); + +// font_driver_render_msg(NULL, "TEST: 123 ABC àüî", NULL); + + + GPU_FinishDrawing(); GPUCMD_Finalize(); ctrGuFlushAndRun(true); @@ -815,7 +838,9 @@ static void ctr_free(void* data) linearFree(ctr->menu.texture_swizzled); linearFree(ctr->menu.frame_coords); linearFree(ctr->empty_framebuffer); + linearFree(ctr->vertex_cache.buffer); linearFree(ctr); +// DEBUG_HOLD(); // gfxExit(); } @@ -929,9 +954,87 @@ static void ctr_viewport_info(void* data, struct video_viewport* vp) *vp = ctr->vp; } +static uintptr_t ctr_load_texture(void *video_data, void *data, + bool threaded, enum texture_filter_type filter_type) +{ + struct texture_image *image = (struct texture_image*)data; + + ctr_texture_t* texture = calloc(1, sizeof(ctr_texture_t)); + uint32_t texsize = image->width * image->height * sizeof(uint32_t); + void* tmpdata; +// texture->data = vramAlloc(image->width * image->height * sizeof(uint32_t)); +// if(!texture->data) + texture->data = linearAlloc(image->width * image->height * sizeof(uint32_t)); + texture->type = filter_type; + texture->width = image->width; + texture->height = image->height; + + + if ((!texture->data)) + { + free(texture); + return 0; + } + if ((texture->width == 1) && (texture->height == 1)) + { + *(uint32_t*)texture->data = *image->pixels; + } + else + { + tmpdata = linearAlloc(image->width * image->height * sizeof(uint32_t)); + // memcpy(tmpdata, image->pixels, image->width * image->height * sizeof(uint32_t)); + int i; + uint32_t* src = (uint32_t*)image->pixels; + uint32_t* dst = (uint32_t*)tmpdata; + for (i = 0; i < image->width * image->height; i++) + { + *dst = ((*src >> 8) & 0x00FF00) | ((*src >> 24) & 0xFF)| ((*src << 8) & 0xFF0000)| ((*src << 24) & 0xFF000000); + dst++; + src++; + } + + + GSPGPU_FlushDataCache(tmpdata, image->width * image->height * sizeof(uint32_t)); + // printf("ctrGuCopyImage 0x%08X, %i, %i, 0x%08X, %i\n", tmpdata, image->width, image->height, texture->data, texture->width); + ctrGuCopyImage(true, tmpdata, image->width, image->height, CTRGU_RGBA8, false, + texture->data, texture->width, CTRGU_RGBA8, true); + + // gspWaitForEvent(GSPGPU_EVENT_PPF, false); + linearFree(tmpdata); + } + + return (uintptr_t)texture; +} + +static void ctr_unload_texture(void *data, uintptr_t handle) +{ + struct ctr_texture *texture = (struct ctr_texture*)handle; + if (!texture) + return; + + if (texture->data) + { + if(((u32)texture->data & 0xFF000000) == 0x1F000000) + vramFree(texture->data); + else + linearFree(texture->data); + } + free(texture); +} + +static void ctr_set_osd_msg(void *data, const char *msg, + const struct font_params *params, void *font) +{ + ctr_video_t* ctr = (ctr_video_t*)data; + + if (ctr->msg_rendering_enabled) + font_driver_render_msg(font, msg, params); +} + + static const video_poke_interface_t ctr_poke_interface = { - NULL, - NULL, + ctr_load_texture, + ctr_unload_texture, NULL, ctr_set_filtering, NULL, /* get_video_output_size */ @@ -944,6 +1047,7 @@ static const video_poke_interface_t ctr_poke_interface = { #ifdef HAVE_MENU ctr_set_texture_frame, ctr_set_texture_enable, + ctr_set_osd_msg, #endif NULL, NULL, diff --git a/gfx/drivers/ctr_gu.h b/gfx/drivers/ctr_gu.h index fb70f52137..d0ca6ffc0c 100644 --- a/gfx/drivers/ctr_gu.h +++ b/gfx/drivers/ctr_gu.h @@ -23,6 +23,8 @@ #include #include +#include "ctr/ctr_debug.h" + #define VIRT_TO_PHYS(vaddr) \ (((u32)(vaddr)) >= 0x14000000 && ((u32)(vaddr)) < 0x1c000000)?(void*)((u32)(vaddr) + 0x0c000000):\ (((u32)(vaddr)) >= 0x1F000000 && ((u32)(vaddr)) < 0x1F600000)?(void*)((u32)(vaddr) - 0x07000000):\ @@ -51,16 +53,6 @@ #define CTR_CPU_TICKS_PER_SECOND 268123480 #define CTR_CPU_TICKS_PER_FRAME 4481134 -#ifndef DEBUG_HOLD -void wait_for_input(void); -#define PRINTFPOS(X,Y) "\x1b["#X";"#Y"H" -#define PRINTF_LINE(X) "\x1b["X";0H" -#define DEBUG_HOLD() do{printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);wait_for_input();}while(0) -#define DEBUG_VAR(X) printf( "%-20s: 0x%08X\n", #X, (u32)(X)) -#define DEBUG_VAR64(X) printf( #X"\r\t\t\t\t : 0x%016llX\n", (u64)(X)) -#endif - - extern u32* gpuCmdBuf; extern u32 gpuCmdBufOffset; extern u32 __linear_heap_size; diff --git a/gfx/drivers_font/ctr_font.c b/gfx/drivers_font/ctr_font.c new file mode 100644 index 0000000000..b5aad4f394 --- /dev/null +++ b/gfx/drivers_font/ctr_font.c @@ -0,0 +1,436 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2016 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include +#include +#include +#include <3ds.h> + +#include "../font_driver.h" +#include "../video_driver.h" +#include "../common/ctr_common.h" +#include "../drivers/ctr_gu.h" +#include "../../ctr/gpu_old.h" + +#include "../../configuration.h" +#include "../../verbosity.h" + +typedef struct +{ + ctr_texture_t texture; + ctr_scale_vector_t scale_vector; + const font_renderer_driver_t* font_driver; + void* font_data; +} ctr_font_t; + +static void* ctr_font_init_font(void* gl_data, const char* font_path, float font_size) +{ + const struct font_atlas* atlas = NULL; + ctr_font_t* font = (ctr_font_t*)calloc(1, sizeof(*font)); + + if (!font) + return NULL; + + font_size = 10; + if (!font_renderer_create_default((const void**)&font->font_driver, + &font->font_data, font_path, font_size)) + { + RARCH_WARN("Couldn't initialize font renderer.\n"); + free(font); + return NULL; + } + + atlas = font->font_driver->get_atlas(font->font_data); + + font->texture.width = next_pow2(atlas->width); + font->texture.height = next_pow2(atlas->height); + font->texture.data = vramAlloc(font->texture.width * font->texture.height); + + uint8_t* tmp = linearAlloc(font->texture.width * font->texture.height); + int i, j; + const uint8_t* src = atlas->buffer; + + for (j = 0; (j < atlas->height) && (j < font->texture.height); j++) + for (i = 0; (i < atlas->width) && (i < font->texture.width); i++) + { + int pos = (i & 0x1) << 0 | ((i & 0x2) << 1) | ((i & 0x4) << 2) | + (j & 0x1) << 1 | ((j & 0x2) << 2) | ((j & 0x4) << 3); + + tmp[((i >> 3) << 6) + ((j >> 3) * ((font->texture.width >> 3) << 6)) + pos ] = src[i + j * atlas->width]; + } + + GSPGPU_FlushDataCache(tmp, font->texture.width * font->texture.height); + ctrGuCopyImage(true, tmp, font->texture.width >> 2, font->texture.height, CTRGU_RGBA8, true, + font->texture.data, font->texture.width >> 2, CTRGU_RGBA8, true); + + linearFree(tmp); + + ctr_set_scale_vector(&font->scale_vector, 400, 240, font->texture.width, font->texture.height); + + return font; +} + +static void ctr_font_free_font(void* data) +{ + ctr_font_t* font = (ctr_font_t*)data; + + if (!font) + return; + + if (font->font_driver && font->font_data) + font->font_driver->free(font->font_data); + + vramFree(font->texture.data); + free(font); +} + +static int ctr_font_get_message_width(void* data, const char* msg, + unsigned msg_len, float scale) +{ + ctr_font_t* font = (ctr_font_t*)data; + + unsigned i; + int delta_x = 0; + + if (!font) + return 0; + + for (i = 0; i < msg_len; i++) + { + const char* msg_tmp = &msg[i]; + unsigned code = utf8_walk(&msg_tmp); + unsigned skip = msg_tmp - &msg[i]; + + if (skip > 1) + i += skip - 1; + + const struct font_glyph* glyph = + font->font_driver->get_glyph(font->font_data, code); + + if (!glyph) /* Do something smarter here ... */ + glyph = font->font_driver->get_glyph(font->font_data, '?'); + + if (!glyph) + continue; + + delta_x += glyph->advance_x; + } + + return delta_x * scale; +} + +static void ctr_font_render_line( + ctr_font_t* font, const char* msg, unsigned msg_len, + float scale, const unsigned int color, float pos_x, + float pos_y, unsigned text_align) +{ + int x, y, delta_x, delta_y; + unsigned width, height; + unsigned i; + + ctr_video_t* ctr = (ctr_video_t*)video_driver_get_ptr(false); + ctr_vertex_t* v; + video_driver_get_size(&width, &height); + + x = roundf(pos_x * width); + y = roundf((1.0f - pos_y) * height); + delta_x = 0; + delta_y = 0; + + + switch (text_align) + { + case TEXT_ALIGN_RIGHT: + x -= ctr_font_get_message_width(font, msg, msg_len, scale); + break; + + case TEXT_ALIGN_CENTER: + x -= ctr_font_get_message_width(font, msg, msg_len, scale) / 2; + break; + } + + if ((ctr->vertex_cache.size - (ctr->vertex_cache.current - ctr->vertex_cache.buffer)) < msg_len) + ctr->vertex_cache.current = ctr->vertex_cache.buffer; + + v = ctr->vertex_cache.current; + + for (i = 0; i < msg_len; i++) + { + int off_x, off_y, tex_x, tex_y, width, height; + const char* msg_tmp = &msg[i]; + unsigned code = utf8_walk(&msg_tmp); + unsigned skip = msg_tmp - &msg[i]; + + if (skip > 1) + i += skip - 1; + + const struct font_glyph* glyph = + font->font_driver->get_glyph(font->font_data, code); + + if (!glyph) /* Do something smarter here ... */ + glyph = font->font_driver->get_glyph(font->font_data, '?'); + + if (!glyph) + continue; + + off_x = glyph->draw_offset_x; + off_y = glyph->draw_offset_y; + tex_x = glyph->atlas_offset_x; + tex_y = glyph->atlas_offset_y; + width = glyph->width; + height = glyph->height; + + + v->x0 = x + off_x + delta_x * scale; + v->y0 = y + off_y + delta_y * scale; + v->u0 = tex_x; + v->v0 = tex_y; + v->x1 = v->x0 + width * scale; + v->y1 = v->y0 + height * scale; + v->u1 = v->u0 + width; + v->v1 = v->v0 + height; + + v++; + delta_x += glyph->advance_x; + delta_y += glyph->advance_y; + } + + ctrGuSetVertexShaderFloatUniform(0, (float*)&font->scale_vector, 1); + GSPGPU_FlushDataCache(ctr->vertex_cache.current, (v - ctr->vertex_cache.current) * sizeof(ctr_vertex_t)); + ctrGuSetAttributeBuffers(2, + VIRT_TO_PHYS(ctr->vertex_cache.current), + CTRGU_ATTRIBFMT(GPU_SHORT, 4) << 0 | + CTRGU_ATTRIBFMT(GPU_SHORT, 4) << 4, + sizeof(ctr_vertex_t)); + + GPU_SetTexEnv(0, + GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, 0), + GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, 0), + 0, + GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_R, GPU_TEVOP_RGB_SRC_ALPHA, 0), + GPU_MODULATE, GPU_MODULATE, + color); +// printf("%s\n", msg); +// DEBUG_VAR(color); +// GPU_SetTexEnv(0, GPU_TEXTURE0, GPU_TEXTURE0, 0, GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_R, 0, 0), GPU_REPLACE, GPU_REPLACE, 0); + ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(font->texture.data), font->texture.width, font->texture.height, + GPU_TEXTURE_MAG_FILTER(GPU_NEAREST) | GPU_TEXTURE_MIN_FILTER(GPU_NEAREST) | + GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), + GPU_L8); + + GPU_SetViewport(NULL, + VIRT_TO_PHYS(ctr->drawbuffers.top.left), + 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, + ctr->video_mode == CTR_VIDEO_MODE_800x240 ? CTR_TOP_FRAMEBUFFER_WIDTH * 2 : CTR_TOP_FRAMEBUFFER_WIDTH); + + GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, v - ctr->vertex_cache.current); + + if (ctr->video_mode == CTR_VIDEO_MODE_3D) + { + GPU_SetViewport(NULL, + VIRT_TO_PHYS(ctr->drawbuffers.top.right), + 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, + CTR_TOP_FRAMEBUFFER_WIDTH); + GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, v - ctr->vertex_cache.current); + } + + + + +// v = font->vertices; +// v->x0 = 0; +// v->y0 = 0; +// v->u0 = 0; +// v->v0 = 0; +// v->x1 = font->texture.width; +// v->y1 = font->texture.height; +// v->u1 = font->texture.width; +// v->v1 = font->texture.height; +// GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); + + GPU_SetTexEnv(0, GPU_TEXTURE0, GPU_TEXTURE0, 0, 0, GPU_REPLACE, GPU_REPLACE, 0); + // DEBUG_VAR(v - font->vertices); + // v = font->vertices; + // printf("OSDMSG: %s\n", msg); + // printf("vertex : (%i,%i,%i,%i) - (%i,%i,%i,%i)\n", + // v->x0, v->y0, v->x1, v->y1, + // v->u0, v->v0, v->u1, v->v1); + +// printf("%s\n", msg); + ctr->vertex_cache.current = v; +} + +static void ctr_font_render_message( + ctr_font_t* font, const char* msg, float scale, + const unsigned int color, float pos_x, float pos_y, + unsigned text_align) +{ + int lines = 0; + float line_height; + + if (!msg || !*msg) + return; + + /* If the font height is not supported just draw as usual */ + if (!font->font_driver->get_line_height) + { + ctr_font_render_line(font, msg, strlen(msg), + scale, color, pos_x, pos_y, text_align); + return; + } + + line_height = scale / font->font_driver->get_line_height(font->font_data); + + for (;;) + { + const char* delim = strchr(msg, '\n'); + + /* Draw the line */ + if (delim) + { + unsigned msg_len = delim - msg; + ctr_font_render_line(font, msg, msg_len, + scale, color, pos_x, pos_y - (float)lines * line_height, + text_align); + msg += msg_len + 1; + lines++; + } + else + { + unsigned msg_len = strlen(msg); + ctr_font_render_line(font, msg, msg_len, + scale, color, pos_x, pos_y - (float)lines * line_height, + text_align); + break; + } + } +} + +static void ctr_font_render_msg(void* data, const char* msg, + const void* userdata) +{ + float x, y, scale, drop_mod, drop_alpha; + unsigned color, color_dark, r, g, b, alpha, r_dark, g_dark, b_dark, alpha_dark; + unsigned width, height; + int drop_x, drop_y; + unsigned max_glyphs; + enum text_alignment text_align; + settings_t* settings = config_get_ptr(); + ctr_font_t* font = (ctr_font_t*)data; + const struct font_params* params = (const struct font_params*)userdata; + + if (!font || !msg || !*msg) + return; + + video_driver_get_size(&width, &height); + + if (params) + { +// printf("%s\n", msg); + x = params->x; + y = params->y; + scale = params->scale; + text_align = params->text_align; + drop_x = params->drop_x; + drop_y = params->drop_y; + drop_mod = params->drop_mod; + drop_alpha = params->drop_alpha; + r = FONT_COLOR_GET_RED(params->color); + g = FONT_COLOR_GET_GREEN(params->color); + b = FONT_COLOR_GET_BLUE(params->color); + alpha = FONT_COLOR_GET_ALPHA(params->color); + color = params->color; +// color = COLOR_ABGR(r, g, b, alpha); + } + else + { + x = settings->video.msg_pos_x; + y = settings->video.msg_pos_y; + scale = 1.0f; + text_align = TEXT_ALIGN_LEFT; + + r = (settings->video.msg_color_r * 255); + g = (settings->video.msg_color_g * 255); + b = (settings->video.msg_color_b * 255); + alpha = 255; + color = COLOR_ABGR(r, g, b, alpha); + + drop_x = -2; + drop_y = -2; + drop_mod = 0.3f; + drop_alpha = 1.0f; + } + + max_glyphs = strlen(msg); + + if (drop_x || drop_y) + max_glyphs *= 2; + + if (drop_x || drop_y) + { + r_dark = r * drop_mod; + g_dark = g * drop_mod; + b_dark = b * drop_mod; + alpha_dark = alpha * drop_alpha; + color_dark = COLOR_ABGR(r_dark, g_dark, b_dark, alpha_dark); + + ctr_font_render_message(font, msg, scale, color_dark, + x + scale * drop_x / width, y + + scale * drop_y / height, text_align); + } + + ctr_font_render_message(font, msg, scale, + color, x, y, text_align); +} + +static const struct font_glyph* ctr_font_get_glyph( + void* data, uint32_t code) +{ + ctr_font_t* font = (ctr_font_t*)data; + + if (!font || !font->font_driver) + return NULL; + + if (!font->font_driver->ident) + return NULL; + + return font->font_driver->get_glyph((void*)font->font_driver, code); +} + +static void ctr_font_flush_block(void* data) +{ + (void)data; +} + +static void ctr_font_bind_block(void* data, void* userdata) +{ + (void)data; +} + + +font_renderer_t ctr_font = +{ + ctr_font_init_font, + ctr_font_free_font, + ctr_font_render_msg, + "ctrfont", + ctr_font_get_glyph, + ctr_font_bind_block, + ctr_font_flush_block, + ctr_font_get_message_width, +}; diff --git a/gfx/font_driver.c b/gfx/font_driver.c index 0c19d4d599..275194d0e1 100644 --- a/gfx/font_driver.c +++ b/gfx/font_driver.c @@ -201,6 +201,34 @@ static bool vita2d_font_init_first( } #endif +#ifdef _3DS +static const font_renderer_t *ctr_font_backends[] = { + &ctr_font +}; + +static bool ctr_font_init_first( + const void **font_driver, void **font_handle, + void *video_data, const char *font_path, float font_size) +{ + unsigned i; + + for (i = 0; ctr_font_backends[i]; i++) + { + void *data = ctr_font_backends[i]->init( + video_data, font_path, font_size); + + if (!data) + continue; + + *font_driver = ctr_font_backends[i]; + *font_handle = data; + return true; + } + + return false; +} +#endif + static bool font_init_first( const void **font_driver, void **font_handle, void *video_data, const char *font_path, float font_size, @@ -230,6 +258,11 @@ static bool font_init_first( case FONT_DRIVER_RENDER_VITA2D: return vita2d_font_init_first(font_driver, font_handle, video_data, font_path, font_size); +#endif +#ifdef _3DS + case FONT_DRIVER_RENDER_CTR: + return ctr_font_init_first(font_driver, font_handle, + video_data, font_path, font_size); #endif case FONT_DRIVER_RENDER_DONT_CARE: /* TODO/FIXME - lookup graphics driver's 'API' */ diff --git a/gfx/font_driver.h b/gfx/font_driver.h index 00727fd4ca..a81de44043 100644 --- a/gfx/font_driver.h +++ b/gfx/font_driver.h @@ -30,6 +30,7 @@ enum font_driver_render_api FONT_DRIVER_RENDER_OPENGL_API, FONT_DRIVER_RENDER_DIRECT3D_API, FONT_DRIVER_RENDER_VITA2D, + FONT_DRIVER_RENDER_CTR, FONT_DRIVER_RENDER_VULKAN_API }; @@ -151,6 +152,7 @@ extern font_renderer_t d3d_xbox360_font; extern font_renderer_t d3d_xdk1_font; extern font_renderer_t d3d_win32_font; extern font_renderer_t vita2d_vita_font; +extern font_renderer_t ctr_font; extern font_renderer_t vulkan_raster_font; extern font_renderer_driver_t stb_font_renderer; diff --git a/griffin/griffin.c b/griffin/griffin.c index 6bb4bfc8ce..6d25db15f1 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -381,6 +381,11 @@ FONTS #include "../gfx/drivers_font/vita2d_font.c" #endif +#if defined(_3DS) +#include "../gfx/drivers_font/ctr_font.c" +#endif + + #if defined(HAVE_VULKAN) #include "../gfx/drivers_font/vulkan_raster_font.c" #endif @@ -950,6 +955,10 @@ MENU #include "../menu/drivers_display/menu_display_vita2d.c" #endif +#ifdef _3DS +#include "../menu/drivers_display/menu_display_ctr.c" +#endif + #endif @@ -957,7 +966,7 @@ MENU #include "../menu/drivers/rgui.c" #endif -#if defined(HAVE_OPENGL) || defined(HAVE_VITA2D) +#if defined(HAVE_OPENGL) || defined(HAVE_VITA2D) || defined(_3DS) #ifdef HAVE_XMB #include "../menu/drivers/xmb.c" #endif diff --git a/menu/drivers_display/menu_display_ctr.c b/menu/drivers_display/menu_display_ctr.c new file mode 100644 index 0000000000..efe7e5d427 --- /dev/null +++ b/menu/drivers_display/menu_display_ctr.c @@ -0,0 +1,196 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2011-2016 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include + +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif + +#include "../menu_display.h" + +#include "../../config.def.h" +#include "../../retroarch.h" +#include "../../gfx/font_driver.h" +#include "../../gfx/video_context_driver.h" +#include "../../gfx/video_shader_driver.h" +#include "../../gfx/common/ctr_common.h" +#include "../../gfx/drivers/ctr_gu.h" +#include "../../ctr/gpu_old.h" + +static const float *menu_display_ctr_get_default_vertices(void) +{ + return NULL; +} + +static const float *menu_display_ctr_get_default_tex_coords(void) +{ + return NULL; +} + +static void *menu_display_ctr_get_default_mvp(void) +{ + return NULL; +} + +static void menu_display_ctr_blend_begin(void) +{ + +} + +static void menu_display_ctr_blend_end(void) +{ + +} + +static void menu_display_ctr_viewport(void *data) +{ + +} + + +static void menu_display_ctr_draw(void *data) +{ + struct ctr_texture *texture = NULL; + const float *color = NULL; + ctr_video_t *ctr = (ctr_video_t*)video_driver_get_ptr(false); + menu_display_ctx_draw_t *draw = (menu_display_ctx_draw_t*)data; + + if (!ctr || !draw) + return; + + texture = (struct ctr_texture*)draw->texture; + color = draw->coords->color; + + if (!texture) + return; + + ctr_scale_vector_t scale_vector; + ctr_set_scale_vector(&scale_vector, + CTR_TOP_FRAMEBUFFER_WIDTH, CTR_TOP_FRAMEBUFFER_HEIGHT, + texture->width, texture->height); + ctrGuSetVertexShaderFloatUniform(0, (float*)&scale_vector, 1); + + if ((ctr->vertex_cache.size - (ctr->vertex_cache.current - ctr->vertex_cache.buffer)) < 1) + ctr->vertex_cache.current = ctr->vertex_cache.buffer; + + ctr_vertex_t* v = ctr->vertex_cache.current++; + + v->x0 = draw->x; + v->y0 = 240 - draw->height - draw->y; + v->x1 = draw->x + draw->width; + v->y1 = v->y0 + draw->height; + v->u0 = 0; + v->v0 = 0; + v->u1 = texture->width; + v->v1 = texture->height; + + ctrGuSetAttributeBuffers(2, + VIRT_TO_PHYS(v), + CTRGU_ATTRIBFMT(GPU_SHORT, 4) << 0 | + CTRGU_ATTRIBFMT(GPU_SHORT, 4) << 4, + sizeof(ctr_vertex_t)); + + color = draw->coords->color; + int colorR = (int)((*color++)*255.f); + int colorG = (int)((*color++)*255.f); + int colorB = (int)((*color++)*255.f); + int colorA = (int)((*color++)*255.f); + + GPU_SetTexEnv(0, + GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, 0), + GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, 0), + 0, + 0, + GPU_MODULATE, GPU_MODULATE, + COLOR_ABGR(colorR,colorG,colorB,colorA) + ); +// GPU_SetTexEnv(0, +// GPU_TEVSOURCES(GPU_CONSTANT, GPU_CONSTANT, 0), +// GPU_TEVSOURCES(GPU_CONSTANT, GPU_CONSTANT, 0), +// 0, +// GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_COLOR, GPU_TEVOP_RGB_SRC_COLOR, 0), +// GPU_REPLACE, GPU_REPLACE, +// 0x3FFFFFFF); + + ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(texture->data), texture->width, texture->height, + GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | + GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), + GPU_RGBA8); + + + GPU_SetViewport(NULL, + VIRT_TO_PHYS(ctr->drawbuffers.top.left), + 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, + ctr->video_mode == CTR_VIDEO_MODE_800x240 ? CTR_TOP_FRAMEBUFFER_WIDTH * 2 : CTR_TOP_FRAMEBUFFER_WIDTH); + + GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); + + if (ctr->video_mode == CTR_VIDEO_MODE_3D) + { + GPU_SetViewport(NULL, + VIRT_TO_PHYS(ctr->drawbuffers.top.right), + 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, + CTR_TOP_FRAMEBUFFER_WIDTH); + GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); + } + + GPU_SetTexEnv(0, GPU_TEXTURE0, GPU_TEXTURE0, 0, 0, GPU_REPLACE, GPU_REPLACE, 0); +// printf("(%i,%i,%i,%i) , (%i,%i)\n", (int)draw->x, (int)draw->y, (int)draw->width, (int)draw->height, texture->width, texture->height); +} + +static void menu_display_ctr_draw_pipeline(void *data) +{ +} + +static void menu_display_ctr_restore_clear_color(void) +{ +// ctr_set_clear_color(RGBA8(0x00, 0x00, 0x00, 0xFF)); +} + +static void menu_display_ctr_clear_color(menu_display_ctx_clearcolor_t *clearcolor) +{ + if (!clearcolor) + return; +// ctr_set_clear_color(RGBA8((int)(clearcolor->r*255.f), +// (int)(clearcolor->g*255.f), +// (int)(clearcolor->b*255.f), +// (int)(clearcolor->a*255.f))); +// ctr_clear_screen(); +} + +static bool menu_display_ctr_font_init_first( + void **font_handle, void *video_data, + const char *font_path, float font_size) +{ + return font_driver_init_first(NULL, font_handle, video_data, + font_path, font_size, true, FONT_DRIVER_RENDER_CTR); +} + +menu_display_ctx_driver_t menu_display_ctx_ctr = { + menu_display_ctr_draw, + menu_display_ctr_draw_pipeline, + menu_display_ctr_viewport, + menu_display_ctr_blend_begin, + menu_display_ctr_blend_end, + menu_display_ctr_restore_clear_color, + menu_display_ctr_clear_color, + menu_display_ctr_get_default_mvp, + menu_display_ctr_get_default_vertices, + menu_display_ctr_get_default_tex_coords, + menu_display_ctr_font_init_first, + MENU_VIDEO_DRIVER_CTR, + "menu_display_ctr", +}; diff --git a/menu/menu_display.c b/menu/menu_display.c index 3820a0abf9..7c95283887 100644 --- a/menu/menu_display.c +++ b/menu/menu_display.c @@ -61,6 +61,9 @@ static menu_display_ctx_driver_t *menu_display_ctx_drivers[] = { #endif #ifdef HAVE_VITA2D &menu_display_ctx_vita2d, +#endif +#ifdef _3DS + &menu_display_ctx_ctr, #endif &menu_display_ctx_null, NULL, @@ -113,6 +116,10 @@ static bool menu_display_check_compatibility( if (string_is_equal(video_driver, "vita2d")) return true; break; + case MENU_VIDEO_DRIVER_CTR: + if (string_is_equal(video_driver, "ctr")) + return true; + break; } return false; diff --git a/menu/menu_display.h b/menu/menu_display.h index 1d5efbe6a8..23b3d2fb0e 100644 --- a/menu/menu_display.h +++ b/menu/menu_display.h @@ -86,7 +86,8 @@ enum menu_display_driver_type MENU_VIDEO_DRIVER_OPENGL, MENU_VIDEO_DRIVER_VULKAN, MENU_VIDEO_DRIVER_DIRECT3D, - MENU_VIDEO_DRIVER_VITA2D + MENU_VIDEO_DRIVER_VITA2D, + MENU_VIDEO_DRIVER_CTR }; typedef struct menu_display_ctx_clearcolor @@ -271,6 +272,7 @@ extern menu_display_ctx_driver_t menu_display_ctx_gl; extern menu_display_ctx_driver_t menu_display_ctx_vulkan; extern menu_display_ctx_driver_t menu_display_ctx_d3d; extern menu_display_ctx_driver_t menu_display_ctx_vita2d; +extern menu_display_ctx_driver_t menu_display_ctx_ctr; extern menu_display_ctx_driver_t menu_display_ctx_null; RETRO_END_DECLS