diff --git a/Makefile.wii b/Makefile.wii index 6965ea3512..00b75ed983 100644 --- a/Makefile.wii +++ b/Makefile.wii @@ -8,7 +8,7 @@ HAVE_LOGGER = 0 HAVE_FILE_LOGGER = 0 PERF_TEST = 0 -PC_DEVELOPMENT_IP_ADDRESS = "192.168.1.7" +PC_DEVELOPMENT_IP_ADDRESS = "192.168.1.100" PC_DEVELOPMENT_UDP_PORT = 3490 # system platform diff --git a/console/griffin/griffin.c b/console/griffin/griffin.c index ab64a6b108..02df0a3a9c 100644 --- a/console/griffin/griffin.c +++ b/console/griffin/griffin.c @@ -199,6 +199,14 @@ DRIVERS ============================================================ */ #include "../../driver.c" +/*============================================================ +SCALERS +============================================================ */ +#include "../../gfx/scaler/filter.c" +#include "../../gfx/scaler/pixconv.c" +#include "../../gfx/scaler/scaler.c" +#include "../../gfx/scaler/scaler_int.c" + /*============================================================ FIFO BUFFER ============================================================ */ diff --git a/console/logger/logger_override.h b/console/logger/logger_override.h index 46601fd351..66a5509e91 100644 --- a/console/logger/logger_override.h +++ b/console/logger/logger_override.h @@ -26,6 +26,10 @@ logger_send("RetroArch Salamander: " __VA_ARGS__); \ } while(0) +#define RARCH_LOG_OUTPUT(...) do { \ + logger_send("RetroArch Salamander [OUTPUT] :: " __VA_ARGS__); \ +} while(0) + #define RARCH_ERR(...) do { \ logger_send("RetroArch Salamander [ERROR] :: " __VA_ARGS__); \ } while(0) @@ -48,6 +52,10 @@ logger_send("RetroArch [WARN] :: " __VA_ARGS__); \ } while(0) +#define RARCH_LOG_OUTPUT(...) do { \ + logger_send("RetroArch [OUTPUT] :: " __VA_ARGS__); \ +} while(0) + #endif #elif defined(HAVE_FILE_LOGGER) @@ -76,6 +84,13 @@ extern FILE * log_fp; } while (0) #endif +#ifndef RARCH_LOG_OUTPUT +#define RARCH_LOG_OUTPUT(...) do { \ + fprintf(log_fp, "RetroArch Salamander [OUTPUT] :: " __VA_ARGS__); \ + fflush(log_fp); \ + } while (0) +#endif + #else #ifndef RARCH_LOG @@ -99,6 +114,13 @@ extern FILE * log_fp; } while (0) #endif +#ifndef RARCH_LOG_OUTPUT +#define RARCH_LOG_OUTPUT(...) do { \ + fprintf(log_fp, "RetroArch [OUTPUT] :: " __VA_ARGS__); \ + fflush(log_fp); \ + } while (0) +#endif + #endif #endif diff --git a/driver.c b/driver.c index a4fafb86c7..2add0b8efd 100644 --- a/driver.c +++ b/driver.c @@ -423,19 +423,32 @@ void uninit_audio(void) } #ifdef HAVE_DYLIB -static void init_filter(void) +static void deinit_filter(void) +{ + g_extern.filter.active = false; + + if (g_extern.filter.lib) + dylib_close(g_extern.filter.lib); + g_extern.filter.lib = NULL; + + free(g_extern.filter.buffer); + free(g_extern.filter.colormap); + free(g_extern.filter.scaler_out); + g_extern.filter.buffer = NULL; + g_extern.filter.colormap = NULL; + g_extern.filter.scaler_out = NULL; + + scaler_ctx_gen_reset(&g_extern.filter.scaler); + memset(&g_extern.filter.scaler, 0, sizeof(g_extern.filter.scaler)); +} + +static void init_filter(bool rgb32) { if (g_extern.filter.active) return; - if (*g_settings.video.filter_path == '\0') + if (!*g_settings.video.filter_path) return; - if (g_extern.system.pix_fmt != RETRO_PIXEL_FORMAT_0RGB1555) - { - RARCH_WARN("CPU filters only support 0RGB1555.\n"); - return; - } - RARCH_LOG("Loading bSNES filter from \"%s\"\n", g_settings.video.filter_path); g_extern.filter.lib = dylib_load(g_settings.video.filter_path); if (!g_extern.filter.lib) @@ -444,6 +457,13 @@ static void init_filter(void) return; } + struct retro_game_geometry *geom = &g_extern.system.av_info.geometry; + unsigned width = geom->max_width; + unsigned height = geom->max_height; + unsigned pow2_x = 0; + unsigned pow2_y = 0; + unsigned maxsize = 0; + g_extern.filter.psize = (void (*)(unsigned*, unsigned*))dylib_proc(g_extern.filter.lib, "filter_size"); g_extern.filter.prender = @@ -454,31 +474,27 @@ static void init_filter(void) if (!g_extern.filter.psize || !g_extern.filter.prender) { RARCH_ERR("Failed to find functions in filter...\n"); - dylib_close(g_extern.filter.lib); - g_extern.filter.lib = NULL; - return; + goto error; } g_extern.filter.active = true; - - struct retro_game_geometry *geom = &g_extern.system.av_info.geometry; - unsigned width = geom->max_width; - unsigned height = geom->max_height; g_extern.filter.psize(&width, &height); - unsigned pow2_x = next_pow2(width); - unsigned pow2_y = next_pow2(height); - unsigned maxsize = pow2_x > pow2_y ? pow2_x : pow2_y; + pow2_x = next_pow2(width); + pow2_y = next_pow2(height); + maxsize = pow2_x > pow2_y ? pow2_x : pow2_y; g_extern.filter.scale = maxsize / RARCH_SCALE_BASE; g_extern.filter.buffer = (uint32_t*)malloc(RARCH_SCALE_BASE * RARCH_SCALE_BASE * g_extern.filter.scale * g_extern.filter.scale * sizeof(uint32_t)); - rarch_assert(g_extern.filter.buffer); + if (!g_extern.filter.buffer) + goto error; g_extern.filter.pitch = RARCH_SCALE_BASE * g_extern.filter.scale * sizeof(uint32_t); g_extern.filter.colormap = (uint32_t*)malloc(0x10000 * sizeof(uint32_t)); - rarch_assert(g_extern.filter.colormap); + if (!g_extern.filter.colormap) + goto error; // Set up conversion map from 16-bit XRGB1555 to 32-bit ARGB. for (unsigned i = 0; i < 0x10000; i++) @@ -492,18 +508,23 @@ static void init_filter(void) b = (b << 3) | (b >> 2); g_extern.filter.colormap[i] = (r << 16) | (g << 8) | (b << 0); } -} -static void deinit_filter(void) -{ - if (!g_extern.filter.active) - return; + g_extern.filter.scaler_out = (uint16_t*)malloc(sizeof(uint16_t) * geom->max_width * geom->max_height); + if (!g_extern.filter.scaler_out) + goto error; - g_extern.filter.active = false; - dylib_close(g_extern.filter.lib); - g_extern.filter.lib = NULL; - free(g_extern.filter.buffer); - free(g_extern.filter.colormap); + g_extern.filter.scaler.scaler_type = SCALER_TYPE_POINT; + g_extern.filter.scaler.in_fmt = rgb32 ? SCALER_FMT_ARGB8888 : SCALER_FMT_RGB565; + g_extern.filter.scaler.out_fmt = SCALER_FMT_0RGB1555; + + if (!scaler_ctx_gen_filter(&g_extern.filter.scaler)) + goto error; + + return; + +error: + RARCH_ERR("CPU filter init failed.\n"); + deinit_filter(); } #endif @@ -542,13 +563,6 @@ static bool init_video_pixel_converter(unsigned size) { RARCH_WARN("0RGB1555 pixel format is deprecated, and will be slower. For 15/16-bit, RGB565 format is preferred.\n"); - // We'll tweak these values later, - // just set most of them to something sane to begin with. - driver.scaler.in_width = - driver.scaler.in_height = - driver.scaler.out_width = - driver.scaler.out_height = size; - driver.scaler.scaler_type = SCALER_TYPE_POINT; driver.scaler.in_fmt = SCALER_FMT_0RGB1555; @@ -567,7 +581,7 @@ static bool init_video_pixel_converter(unsigned size) void init_video_input(void) { #ifdef HAVE_DYLIB - init_filter(); + init_filter(g_extern.system.pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888); #endif #ifdef HAVE_XML diff --git a/general.h b/general.h index 822e70acba..69e604526b 100644 --- a/general.h +++ b/general.h @@ -355,6 +355,10 @@ struct global void (*psize)(unsigned *width, unsigned *height); void (*prender)(uint32_t *colormap, uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, unsigned width, unsigned height); + + // CPU filters only work on *XRGB1555*. We have to convert to XRGB1555 first. + struct scaler_ctx scaler; + uint16_t *scaler_out; } filter; msg_queue_t *msg_queue; diff --git a/gfx/context/glx_ctx.c b/gfx/context/glx_ctx.c index c1aee3f2e9..12e6e39119 100644 --- a/gfx/context/glx_ctx.c +++ b/gfx/context/glx_ctx.c @@ -237,6 +237,8 @@ static bool gfx_ctx_set_video_mode( sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); + int x_off = 0; + int y_off = 0; bool windowed_full = g_settings.video.windowed_fullscreen; bool true_full = false; @@ -264,8 +266,6 @@ static bool gfx_ctx_set_video_mode( if (g_settings.video.monitor_index) g_screen = g_settings.video.monitor_index - 1; - int x_off = 0; - int y_off = 0; #ifdef HAVE_XINERAMA if (fullscreen || g_screen != 0) { diff --git a/gfx/context/x11_common.c b/gfx/context/x11_common.c index b0f7a02d2f..67cd53a9a0 100644 --- a/gfx/context/x11_common.c +++ b/gfx/context/x11_common.c @@ -199,13 +199,13 @@ static XineramaScreenInfo *x11_query_screens(Display *dpy, int *num_screens) { int major, minor; if (!XineramaQueryExtension(dpy, &major, &minor)) - return false; + return NULL; XineramaQueryVersion(dpy, &major, &minor); RARCH_LOG("[X11]: Xinerama version: %d.%d.\n", major, minor); if (!XineramaIsActive(dpy)) - return false; + return NULL; return XineramaQueryScreens(dpy, num_screens); } diff --git a/gfx/context/xegl_ctx.c b/gfx/context/xegl_ctx.c index bd6a94e8f9..cfa81b37a9 100644 --- a/gfx/context/xegl_ctx.c +++ b/gfx/context/xegl_ctx.c @@ -263,6 +263,8 @@ static bool gfx_ctx_set_video_mode( XVisualInfo *vi = NULL; bool windowed_full = g_settings.video.windowed_fullscreen; bool true_full = false; + int x_off = 0; + int y_off = 0; EGLint vid; if (!eglGetConfigAttrib(g_egl_dpy, g_config, EGL_NATIVE_VISUAL_ID, &vid)) @@ -292,8 +294,6 @@ static bool gfx_ctx_set_video_mode( if (g_settings.video.monitor_index) g_screen = g_settings.video.monitor_index - 1; - int x_off = 0; - int y_off = 0; #ifdef HAVE_XINERAMA if (fullscreen || g_screen != 0) { diff --git a/gfx/scaler/pixconv.c b/gfx/scaler/pixconv.c index 5318b9ef80..4ac0e8297f 100644 --- a/gfx/scaler/pixconv.c +++ b/gfx/scaler/pixconv.c @@ -27,6 +27,61 @@ #include #endif +#if defined(__SSE2_) +void conv_rgb565_0rgb1555(void *output_, const void *input_, + int width, int height, + int out_stride, int in_stride) +{ + const uint16_t *input = (const uint16_t*)input_; + uint16_t *output = (uint16_t*)output_; + + int max_width = width - 7; + + const __m128i hi_mask = _mm_set1_epi16(0x7fe0); + const __m128i lo_mask = _mm_set1_epi16(0x1f); + + for (int h = 0; h < height; h++, output += out_stride >> 1, input += in_stride >> 1) + { + int w; + for (w = 0; w < max_width; w += 8) + { + const __m128i in = _mm_loadu_si128((const __m128i*)(input + w)); + __m128i hi = _mm_and_si128(_mm_slli_epi16(in, 1), hi_mask); + __m128i lo = _mm_and_si128(in, lo_mask); + _mm_storeu_si128((__m128i*)(output + w), _mm_or_si128(hi, lo)); + } + + for (; w < width; w++) + { + uint16_t col = input[w]; + uint16_t hi = (col >> 1) & 0x7fe0; + uint16_t lo = col & 0x1f; + output[w] = hi | lo; + } + } +} +#else +void conv_rgb565_0rgb1555(void *output_, const void *input_, + int width, int height, + int out_stride, int in_stride) +{ + const uint16_t *input = (const uint16_t*)input_; + uint16_t *output = (uint16_t*)output_; + + for (int h = 0; h < height; h++, output += out_stride >> 1, input += in_stride >> 1) + { + for (int w = 0; w < width; w++) + { + uint16_t col = input[w]; + uint16_t hi = (col >> 1) & 0x7fe0; + uint16_t lo = col & 0x1f; + output[w] = hi | lo; + } + } +} + +#endif + #if defined(__SSE2__) void conv_0rgb1555_rgb565(void *output_, const void *input_, int width, int height, diff --git a/gfx/scaler/pixconv.h b/gfx/scaler/pixconv.h index 9cdb7d9182..0070969300 100644 --- a/gfx/scaler/pixconv.h +++ b/gfx/scaler/pixconv.h @@ -24,6 +24,10 @@ void conv_0rgb1555_rgb565(void *output, const void *input, int width, int height, int out_stride, int in_stride); +void conv_rgb565_0rgb1555(void *output, const void *input, + int width, int height, + int out_stride, int in_stride); + void conv_rgb565_argb8888(void *output, const void *input, int width, int height, int out_stride, int in_stride); diff --git a/gfx/scaler/scaler.c b/gfx/scaler/scaler.c index 0ea0f7ffc2..bd92a7c95b 100644 --- a/gfx/scaler/scaler.c +++ b/gfx/scaler/scaler.c @@ -74,6 +74,8 @@ static bool set_direct_pix_conv(struct scaler_ctx *ctx) ctx->direct_pixconv = conv_rgb565_bgr24; else if (ctx->in_fmt == SCALER_FMT_0RGB1555 && ctx->out_fmt == SCALER_FMT_RGB565) ctx->direct_pixconv = conv_0rgb1555_rgb565; + else if (ctx->in_fmt == SCALER_FMT_RGB565 && ctx->out_fmt == SCALER_FMT_0RGB1555) + ctx->direct_pixconv = conv_rgb565_0rgb1555; else if (ctx->in_fmt == SCALER_FMT_BGR24 && ctx->out_fmt == SCALER_FMT_ARGB8888) ctx->direct_pixconv = conv_bgr24_argb8888; else if (ctx->in_fmt == SCALER_FMT_ARGB8888 && ctx->out_fmt == SCALER_FMT_0RGB1555) diff --git a/gx/gx_video.c b/gx/gx_video.c index 6fe6796190..87f1117e0c 100644 --- a/gx/gx_video.c +++ b/gx/gx_video.c @@ -135,12 +135,6 @@ void gx_set_video_mode(unsigned fbWidth, unsigned lines) break; } - if (lines == 0 || fbWidth == 0) - { - VIDEO_GetPreferredMode(&gx_mode); - goto config; - } - if (lines <= max_height / 2) { modetype = VI_NON_INTERLACE; @@ -151,6 +145,12 @@ void gx_set_video_mode(unsigned fbWidth, unsigned lines) modetype = (progressive) ? VI_PROGRESSIVE : VI_INTERLACE; } + if (lines == 0 || fbWidth == 0) + { + VIDEO_GetPreferredMode(&gx_mode); + goto config; + } + if (lines > max_height) lines = max_height; if (fbWidth > max_width) @@ -236,6 +236,7 @@ config: GX_SetFieldMode(gx_mode.field_rendering, (gx_mode.viHeight == 2 * gx_mode.xfbHeight) ? GX_ENABLE : GX_DISABLE); GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); GX_InvalidateTexAll(); + GX_Flush(); g_current_framebuf = 0; } @@ -280,7 +281,7 @@ static void init_texture(unsigned width, unsigned height) { unsigned g_filter = g_settings.video.smooth ? GX_LINEAR : GX_NEAR; - GX_InitTexObj(&g_tex.obj, g_tex.data, width, height, GX_TF_RGB5A3, GX_CLAMP, GX_CLAMP, GX_FALSE); + GX_InitTexObj(&g_tex.obj, g_tex.data, width, height, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); GX_InitTexObjLOD(&g_tex.obj, g_filter, g_filter, 0, 0, 0, GX_TRUE, GX_FALSE, GX_ANISO_1); GX_InitTexObj(&menu_tex.obj, menu_tex.data, RGUI_WIDTH, RGUI_HEIGHT, GX_TF_RGB5A3, GX_CLAMP, GX_CLAMP, GX_FALSE); GX_InitTexObjLOD(&menu_tex.obj, g_filter, g_filter, 0, 0, 0, GX_TRUE, GX_FALSE, GX_ANISO_1); @@ -439,7 +440,7 @@ static void gx_start(void) #ifdef ASM_BLITTER static __attribute__ ((noinline)) void update_texture_asm(const uint32_t *src, const uint32_t *dst, - unsigned width, unsigned height, unsigned pitch, unsigned ormask) + unsigned width, unsigned height, unsigned pitch) { register uint32_t tmp0, tmp1, tmp2, tmp3, line2, line2b, line3, line3b, line4, line4b, line5; @@ -461,31 +462,23 @@ static __attribute__ ((noinline)) void update_texture_asm(const uint32_t *src, c " mr %[tmp0], %[src] \n" "1: lwz %[tmp1], 0(%[src]) \n" - " or %[tmp1], %[tmp1], %[ormask] \n" " stwu %[tmp1], 8(%[dst]) \n" " lwz %[tmp2], 4(%[src]) \n" - " or %[tmp2], %[tmp2], %[ormask] \n" " stwu %[tmp2], 8(%[tmp3]) \n" " lwzx %[tmp1], %[line2], %[src] \n" - " or %[tmp1], %[tmp1], %[ormask] \n" " stwu %[tmp1], 8(%[dst]) \n" " lwzx %[tmp2], %[line2b], %[src] \n" - " or %[tmp2], %[tmp2], %[ormask] \n" " stwu %[tmp2], 8(%[tmp3]) \n" " lwzx %[tmp1], %[line3], %[src] \n" - " or %[tmp1], %[tmp1], %[ormask] \n" " stwu %[tmp1], 8(%[dst]) \n" " lwzx %[tmp2], %[line3b], %[src] \n" - " or %[tmp2], %[tmp2], %[ormask] \n" " stwu %[tmp2], 8(%[tmp3]) \n" " lwzx %[tmp1], %[line4], %[src] \n" - " or %[tmp1], %[tmp1], %[ormask] \n" " stwu %[tmp1], 8(%[dst]) \n" " lwzx %[tmp2], %[line4b], %[src] \n" - " or %[tmp2], %[tmp2], %[ormask] \n" " stwu %[tmp2], 8(%[tmp3]) \n" " addi %[src], %[src], 8 \n" @@ -509,8 +502,7 @@ static __attribute__ ((noinline)) void update_texture_asm(const uint32_t *src, c : [src] "b" (src), [width] "b" (width), [height] "b" (height), - [pitch] "b" (pitch), - [ormask] "b" (ormask) + [pitch] "b" (pitch) ); } @@ -522,14 +514,14 @@ static __attribute__ ((noinline)) void update_texture_asm(const uint32_t *src, c uint32_t *tmp_dst = dst; \ for (unsigned x = 0; x < width2; x += 8, tmp_src += 8, tmp_dst += 32) \ { \ - tmp_dst[ 0 + off] = RGB15toRGB5A3(tmp_src[0]); \ - tmp_dst[ 1 + off] = RGB15toRGB5A3(tmp_src[1]); \ - tmp_dst[ 8 + off] = RGB15toRGB5A3(tmp_src[2]); \ - tmp_dst[ 9 + off] = RGB15toRGB5A3(tmp_src[3]); \ - tmp_dst[16 + off] = RGB15toRGB5A3(tmp_src[4]); \ - tmp_dst[17 + off] = RGB15toRGB5A3(tmp_src[5]); \ - tmp_dst[24 + off] = RGB15toRGB5A3(tmp_src[6]); \ - tmp_dst[25 + off] = RGB15toRGB5A3(tmp_src[7]); \ + tmp_dst[ 0 + off] = tmp_src[0]; \ + tmp_dst[ 1 + off] = tmp_src[1]; \ + tmp_dst[ 8 + off] = tmp_src[2]; \ + tmp_dst[ 9 + off] = tmp_src[3]; \ + tmp_dst[16 + off] = tmp_src[4]; \ + tmp_dst[17 + off] = tmp_src[5]; \ + tmp_dst[24 + off] = tmp_src[6]; \ + tmp_dst[25 + off] = tmp_src[7]; \ } \ src2 += tmp_pitch; \ } @@ -543,7 +535,7 @@ static void update_texture(const uint32_t *src, #ifdef ASM_BLITTER if (width && height && !(width & 3) && !(height & 3)) { - update_texture_asm(src, g_tex.data, width, height, pitch, 0x80008000U); + update_texture_asm(src, g_tex.data, width, height, pitch); } else #endif @@ -559,13 +551,10 @@ static void update_texture(const uint32_t *src, uint32_t *dst = g_tex.data; for (unsigned i = 0; i < height; i += 4, dst += 4 * width2) { - // Set MSB to get full RGB555. -#define RGB15toRGB5A3(col) ((col) | 0x80008000u) BLIT_LINE(0) BLIT_LINE(2) BLIT_LINE(4) BLIT_LINE(6) -#undef RGB15toRGB5A3 } } } @@ -573,7 +562,7 @@ static void update_texture(const uint32_t *src, if(gx->menu_render) { #ifdef ASM_BLITTER - update_texture_asm(gx->menu_data, menu_tex.data, RGUI_WIDTH, RGUI_HEIGHT, RGUI_WIDTH * 2, 0x00000000U); + update_texture_asm(gx->menu_data, menu_tex.data, RGUI_WIDTH, RGUI_HEIGHT, RGUI_WIDTH * 2); #else unsigned tmp_pitch = (RGUI_WIDTH * 2) >> 2; unsigned width2 = RGUI_WIDTH >> 1; @@ -582,12 +571,10 @@ static void update_texture(const uint32_t *src, uint32_t *dst = menu_tex.data; for (unsigned i = 0; i < RGUI_HEIGHT; i += 4, dst += 4 * width2) { -#define RGB15toRGB5A3(col) (col) BLIT_LINE(0) BLIT_LINE(2) BLIT_LINE(4) BLIT_LINE(6) -#undef RGB15toRGB5A3 } #endif } diff --git a/retroarch.c b/retroarch.c index 0a804e3754..14b937662f 100644 --- a/retroarch.c +++ b/retroarch.c @@ -283,11 +283,19 @@ static void video_frame(const void *data, unsigned width, unsigned height, size_ #ifdef HAVE_DYLIB if (g_extern.filter.active && data) { + struct scaler_ctx *scaler = &g_extern.filter.scaler; + scaler->in_width = scaler->out_width = width; + scaler->in_height = scaler->out_height = height; + scaler->in_stride = pitch; + scaler->out_stride = width * sizeof(uint16_t); + + scaler_ctx_scale(scaler, g_extern.filter.scaler_out, data); + unsigned owidth = width; unsigned oheight = height; g_extern.filter.psize(&owidth, &oheight); g_extern.filter.prender(g_extern.filter.colormap, g_extern.filter.buffer, - g_extern.filter.pitch, (const uint16_t*)data, pitch, width, height); + g_extern.filter.pitch, g_extern.filter.scaler_out, scaler->out_stride, width, height); #ifdef HAVE_FFMPEG if (g_extern.recording && g_settings.video.post_filter_record)