diff --git a/Makefile b/Makefile index d66054369c..03b97f27a0 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,8 @@ OBJ = frontend/frontend.o \ gfx/scaler/pixconv.o \ gfx/scaler/scaler_int.o \ gfx/scaler/scaler_filter.o \ - gfx/image/image.o \ + gfx/image/image_rpng.o \ + gfx/image_context.o \ gfx/fonts/fonts.o \ gfx/fonts/bitmapfont.o \ audio/resampler.o \ @@ -318,6 +319,7 @@ ifeq ($(HAVE_FREETYPE), 1) endif ifeq ($(HAVE_SDL_IMAGE), 1) + OBJ += gfx/image/image_sdl.o LIBS += $(SDL_IMAGE_LIBS) DEFINES += $(SDL_IMAGE_CFLAGS) endif diff --git a/Makefile.emscripten b/Makefile.emscripten index 3b38873fff..7227b69846 100644 --- a/Makefile.emscripten +++ b/Makefile.emscripten @@ -38,7 +38,8 @@ OBJ = frontend/platform/platform_emscripten.o \ gfx/shader_parse.o \ gfx/fonts/fonts.o \ gfx/fonts/bitmapfont.o \ - gfx/image/image.o \ + gfx/image/image_rpng.o \ + gfx/image_context.o \ audio/resampler.o \ audio/sinc.o \ audio/cc_resampler.o \ diff --git a/Makefile.win b/Makefile.win index ea50c31932..f57e6e1bb1 100644 --- a/Makefile.win +++ b/Makefile.win @@ -43,7 +43,8 @@ OBJ = frontend/frontend.o \ gfx/shader_parse.o \ gfx/fonts/fonts.o \ gfx/fonts/bitmapfont.o \ - gfx/image/image.o \ + gfx/image/image_rpng.o \ + gfx/image_context.o \ audio/resampler.o \ audio/sinc.o \ audio/cc_resampler.o \ @@ -146,6 +147,7 @@ ifeq ($(HAVE_OPENGL), 1) endif ifeq ($(HAVE_SDL_IMAGE), 1) + OBJ += gfx/image/image_sdl.o LIBS += -lSDL_image DEFINES += -DHAVE_SDL_IMAGE endif diff --git a/config.def.h b/config.def.h index 5e9a4bb87f..7869d94e8d 100644 --- a/config.def.h +++ b/config.def.h @@ -87,6 +87,11 @@ enum INPUT_RWEBINPUT, INPUT_NULL, + IMAGE_SDL, + IMAGE_XDK, + IMAGE_PS3, + IMAGE_RPNG, + CAMERA_V4L2, CAMERA_RWEBCAM, CAMERA_ANDROID, @@ -200,6 +205,14 @@ enum #define INPUT_DEFAULT_DRIVER INPUT_NULL #endif +#if defined(__CELLOS_LV2__) +#define IMAGE_DEFAULT_DRIVER IMAGE_PS3 +#elif defined(_XBOX1) +#define IMAGE_DEFAULT_DRIVER IMAGE_XDK +#else +#define IMAGE_DEFAULT_DRIVER IMAGE_RPNG +#endif + #if defined(HAVE_V4L2) #define CAMERA_DEFAULT_DRIVER CAMERA_V4L2 #elif defined(EMSCRIPTEN) diff --git a/driver.c b/driver.c index 29d53a5702..ac87e9f3f9 100644 --- a/driver.c +++ b/driver.c @@ -509,6 +509,7 @@ void init_drivers_pre(void) #ifdef HAVE_CAMERA find_camera_driver(); #endif + find_image_driver(); #ifdef HAVE_LOCATION find_location_driver(); #endif @@ -926,6 +927,8 @@ void uninit_drivers(void) uninit_video_input(); + driver.image = NULL; + #ifdef HAVE_CAMERA uninit_camera(); @@ -1484,6 +1487,7 @@ static bool init_video_pixel_converter(unsigned size) return true; } + void init_video_input(void) { rarch_init_filter(g_extern.system.pix_fmt); diff --git a/driver.h b/driver.h index 2ab74b4a86..43464c1fcb 100644 --- a/driver.h +++ b/driver.h @@ -24,7 +24,7 @@ #include #include "msvc/msvc_compat.h" #include "gfx/scaler/scaler.h" -#include "gfx/image/image.h" +#include "gfx/image_context.h" #include "gfx/filters/softfilter.h" #include "audio/filters/rarch_dsp.h" #include "input/overlay.h" @@ -449,6 +449,7 @@ enum rarch_display_type typedef struct driver { const audio_driver_t *audio; + const image_ctx_driver_t *image; const video_driver_t *video; const input_driver_t *input; #ifdef HAVE_OSK @@ -543,6 +544,8 @@ void uninit_drivers(void); void global_init_drivers(void); void global_uninit_drivers(void); +void init_image_input(void); + void init_video_input(void); void uninit_video_input(void); void init_audio(void); diff --git a/frontend/menu/backend/menu_common_backend.c b/frontend/menu/backend/menu_common_backend.c index 7182083bfa..a0dd045b76 100644 --- a/frontend/menu/backend/menu_common_backend.c +++ b/frontend/menu/backend/menu_common_backend.c @@ -356,6 +356,7 @@ static void menu_common_entries_init(void *data, unsigned menu_type) file_list_push(rgui->selection_buf, "Audio Device", RGUI_SETTINGS_DRIVER_AUDIO_DEVICE, 0); file_list_push(rgui->selection_buf, "Audio Resampler", RGUI_SETTINGS_DRIVER_AUDIO_RESAMPLER, 0); file_list_push(rgui->selection_buf, "Input Driver", RGUI_SETTINGS_DRIVER_INPUT, 0); + file_list_push(rgui->selection_buf, "Image Driver", RGUI_SETTINGS_DRIVER_IMAGE, 0); #ifdef HAVE_CAMERA file_list_push(rgui->selection_buf, "Camera Driver", RGUI_SETTINGS_DRIVER_CAMERA, 0); #endif @@ -3095,6 +3096,12 @@ static int menu_common_setting_set(void *data, unsigned setting, unsigned action else if (action == RGUI_ACTION_RIGHT) find_next_input_driver(); break; + case RGUI_SETTINGS_DRIVER_IMAGE: + if (action == RGUI_ACTION_LEFT) + find_prev_image_driver(); + else if (action == RGUI_ACTION_RIGHT) + find_next_image_driver(); + break; #ifdef HAVE_CAMERA case RGUI_SETTINGS_DRIVER_CAMERA: if (action == RGUI_ACTION_LEFT) @@ -3860,6 +3867,9 @@ static void menu_common_setting_set_label(char *type_str, size_t type_str_size, case RGUI_SETTINGS_DRIVER_INPUT: strlcpy(type_str, g_settings.input.driver, type_str_size); break; + case RGUI_SETTINGS_DRIVER_IMAGE: + strlcpy(type_str, g_settings.image.driver, type_str_size); + break; #ifdef HAVE_CAMERA case RGUI_SETTINGS_DRIVER_CAMERA: strlcpy(type_str, g_settings.camera.driver, type_str_size); diff --git a/frontend/menu/backend/menu_common_backend.h b/frontend/menu/backend/menu_common_backend.h index e8fd4a1463..3dca34870a 100644 --- a/frontend/menu/backend/menu_common_backend.h +++ b/frontend/menu/backend/menu_common_backend.h @@ -100,6 +100,7 @@ typedef enum RGUI_SETTINGS_DRIVER_AUDIO_DEVICE, RGUI_SETTINGS_DRIVER_AUDIO_RESAMPLER, RGUI_SETTINGS_DRIVER_INPUT, + RGUI_SETTINGS_DRIVER_IMAGE, RGUI_SETTINGS_DRIVER_CAMERA, RGUI_SETTINGS_DRIVER_LOCATION, RGUI_SETTINGS_DRIVER_MENU, diff --git a/frontend/menu/disp/rmenu.c b/frontend/menu/disp/rmenu.c index 720776d2ab..6cfcfe82f1 100644 --- a/frontend/menu/disp/rmenu.c +++ b/frontend/menu/disp/rmenu.c @@ -437,7 +437,9 @@ static void rmenu_init_assets(void *data) return; menu_texture = (struct texture_image*)calloc(1, sizeof(*menu_texture)); - texture_image_load(g_extern.menu_texture_path, menu_texture); + + if (driver.image && driver.menu->load) + driver.image->load(driver.video_data, g_extern.menu_texture_path, menu_texture); rgui->width = menu_texture->width; rgui->height = menu_texture->height; @@ -455,7 +457,9 @@ static void *rmenu_init(void) static void rmenu_free_assets(void *data) { - texture_image_free(menu_texture); + if (driver.image && driver.image->free) + driver.image->free(driver.video_data, menu_texture); + menu_texture_inited = false; } diff --git a/general.h b/general.h index 21d4798d38..48988ed5d1 100644 --- a/general.h +++ b/general.h @@ -193,6 +193,11 @@ struct settings } menu; #endif + struct + { + char driver[32]; + } image; + #ifdef HAVE_CAMERA struct { diff --git a/gfx/context/androidegl_ctx.c b/gfx/context/androidegl_ctx.c index 8ce5e86b97..93ae1a8275 100644 --- a/gfx/context/androidegl_ctx.c +++ b/gfx/context/androidegl_ctx.c @@ -22,7 +22,6 @@ #include #include "../../frontend/platform/platform_android.h" -#include "../image/image.h" #include "../fonts/gl_font.h" #include diff --git a/gfx/context/apple_gl_ctx.c b/gfx/context/apple_gl_ctx.c index 9a493640c8..2186ba70a2 100644 --- a/gfx/context/apple_gl_ctx.c +++ b/gfx/context/apple_gl_ctx.c @@ -17,7 +17,6 @@ #include "../../driver.h" #include "../gfx_common.h" #include "../gl_common.h" -#include "../image/image.h" #include "../fonts/gl_font.h" #include diff --git a/gfx/context/bbqnx_ctx.c b/gfx/context/bbqnx_ctx.c index 12d0cdd1f2..78d6877995 100644 --- a/gfx/context/bbqnx_ctx.c +++ b/gfx/context/bbqnx_ctx.c @@ -27,8 +27,6 @@ #include #include -#include "../image/image.h" - #include "../fonts/gl_font.h" #include diff --git a/gfx/context/x11_common.c b/gfx/context/x11_common.c index e492c2320b..3dd180e852 100644 --- a/gfx/context/x11_common.c +++ b/gfx/context/x11_common.c @@ -18,7 +18,6 @@ #include #include #include -#include "../image/image.h" #include "../../general.h" #include "../../input/input_common.h" #include "../../input/keyboard_line.h" diff --git a/gfx/gl.c b/gfx/gl.c index db556b0d74..993fe5dc0b 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -22,7 +22,7 @@ #include "../driver.h" #include "../performance.h" #include "scaler/scaler.h" -#include "image/image.h" +#include "image_context.h" #include "../file.h" #include diff --git a/gfx/image/image_ps3.c b/gfx/image/image_ps3.c index 229ca56c08..6adaecc834 100644 --- a/gfx/image/image_ps3.c +++ b/gfx/image/image_ps3.c @@ -18,7 +18,7 @@ #include "../../config.h" #endif -#include "image.h" +#include "../image_context.h" #include #include @@ -77,7 +77,7 @@ static int img_free(void *ptr, void *a) Image decompression - libJPEG ********************************************************************************/ -static bool ps3graphics_load_jpeg(const char *path, struct texture_image *out_img) +static bool ps3_load_jpeg(const char *path, struct texture_image *out_img) { size_t img_size; #ifndef __PSL1GHT__ @@ -178,7 +178,6 @@ static bool ps3graphics_load_jpeg(const char *path, struct texture_image *out_im return true; error: - RARCH_ERR("ps3graphics_load_jpeg(): error.\n"); if (out_img->pixels) free(out_img->pixels); out_img->pixels = 0; @@ -193,7 +192,7 @@ error: Image decompression - libPNG ********************************************************************************/ -static bool ps3graphics_load_png(const char *path, struct texture_image *out_img) +static bool ps3_load_png(const char *path, struct texture_image *out_img) { size_t img_size; #ifndef __PSL1GHT__ @@ -294,8 +293,6 @@ static bool ps3graphics_load_png(const char *path, struct texture_image *out_img return true; error: - RARCH_ERR("ps3graphics_load_png(): error.\n"); - if (out_img->pixels) free(out_img->pixels); out_img->pixels = 0; @@ -307,25 +304,39 @@ error: return false; } -bool texture_image_load(const char *path, struct texture_image *out_img) +static bool ps3_image_load(void *data, const char *path, void *image_data) { + (void)data; + struct texture_image *out_img = (struct texture_image*)image_data; + + if (!out_img) + return false; + if(strstr(path, ".PNG") != NULL || strstr(path, ".png") != NULL) { - if (!ps3graphics_load_png(path, out_img)) + if (!ps3_load_png(path, out_img)) return false; } else { - if (!ps3graphics_load_jpeg(path, out_img)) + if (!ps3_load_jpeg(path, out_img)) return false; } return true; } -void texture_image_free(struct texture_image *img) +static void ps3_image_free(void *data, void *image_data) { + struct texture_image *img = (struct texture_image*)image_data; + if (img->pixels) free(img->pixels); memset(img, 0, sizeof(*img)); } + +const image_ctx_driver_t image_ctx_ps3 = { + ps3_image_load, + ps3_image_free, + "ps3", +}; diff --git a/gfx/image/image.c b/gfx/image/image_rpng.c similarity index 65% rename from gfx/image/image.c rename to gfx/image/image_rpng.c index c1bb249d22..562cb42c61 100644 --- a/gfx/image/image.c +++ b/gfx/image/image_rpng.c @@ -17,7 +17,7 @@ #include "../../config.h" #endif -#include "image.h" +#include "../image_context.h" #include "../../file.h" #include @@ -26,84 +26,7 @@ #include "../../general.h" #include "../rpng/rpng.h" -#ifdef HAVE_SDL_IMAGE - -#include "SDL_image.h" -bool texture_image_load_argb_shift(const char *path, struct texture_image *out_img, - unsigned a_shift, unsigned r_shift, unsigned g_shift, unsigned b_shift) -{ - int y, x; - SDL_Surface *img = IMG_Load(path); - if (!img) - return false; - - out_img->width = img->w; - out_img->height = img->h; - - size_t size = out_img->width * out_img->height * sizeof(uint32_t); - out_img->pixels = (uint32_t*)malloc(size); - if (!out_img->pixels) - { - SDL_FreeSurface(img); - return false; - } - - const SDL_PixelFormat *fmt = img->format; - - RARCH_LOG("SDL_image: %dx%d @ %d bpp\n", img->w, img->h, img->format->BitsPerPixel); - if (img->format->BitsPerPixel == 32) - { - for (y = 0; y < img->h; y++) - { - uint32_t *dst = out_img->pixels + y * img->w; - const uint32_t *src = (const uint32_t*)img->pixels + y * img->pitch / sizeof(uint32_t); - - for (x = 0; x < img->w; x++) - { - uint32_t r = (src[x] & fmt->Rmask) >> fmt->Rshift; - uint32_t g = (src[x] & fmt->Gmask) >> fmt->Gshift; - uint32_t b = (src[x] & fmt->Bmask) >> fmt->Bshift; - uint32_t a = (src[x] & fmt->Amask) >> fmt->Ashift; - dst[x] = (a << a_shift) | (r << r_shift) | (g << g_shift) | (b << b_shift); - } - } - } - else if (img->format->BitsPerPixel == 24) - { - for (y = 0; y < img->h; y++) - { - uint32_t *dst = out_img->pixels + y * img->w; - const uint8_t *src = (const uint8_t*)img->pixels + y * img->pitch; - - for (x = 0; x < img->w; x++) - { - // Correct? - uint32_t color = 0; - color |= src[3 * x + 0] << 0; - color |= src[3 * x + 1] << 8; - color |= src[3 * x + 2] << 16; - uint32_t r = (color & fmt->Rmask) >> fmt->Rshift; - uint32_t g = (color & fmt->Gmask) >> fmt->Gshift; - uint32_t b = (color & fmt->Bmask) >> fmt->Bshift; - dst[x] = (0xff << a_shift) | (r << r_shift) | (g << g_shift) | (b << b_shift); - } - } - } - else - { - RARCH_ERR("8-bit and 16-bit image support are not implemented.\n"); - SDL_FreeSurface(img); - return false; - } - - SDL_FreeSurface(img); - - return true; -} - -#else - -static bool texture_image_load_tga_shift(const char *path, struct texture_image *out_img, +static bool rpng_image_load_tga_shift(const char *path, struct texture_image *out_img, unsigned a_shift, unsigned r_shift, unsigned g_shift, unsigned b_shift) { unsigned i; @@ -185,18 +108,21 @@ static bool texture_image_load_tga_shift(const char *path, struct texture_image return true; } -bool texture_image_load_argb_shift(const char *path, struct texture_image *out_img, +static bool rpng_image_load_argb_shift(const char *path, struct texture_image *out_img, unsigned a_shift, unsigned r_shift, unsigned g_shift, unsigned b_shift) { unsigned i; (void)i; + if (strstr(path, ".tga")) - return texture_image_load_tga_shift(path, out_img, a_shift, r_shift, g_shift, b_shift); + return rpng_image_load_tga_shift(path, out_img, a_shift, r_shift, g_shift, b_shift); #ifdef HAVE_ZLIB else if (strstr(path, ".png")) { - RARCH_LOG("[RPNG]: Using RPNG loader.\n"); bool ret = rpng_load_image_argb(path, &out_img->pixels, &out_img->width, &out_img->height); + + RARCH_LOG("[RPNG]: Using RPNG loader.\n"); + if (!ret) return false; @@ -205,6 +131,7 @@ bool texture_image_load_argb_shift(const char *path, struct texture_image *out_i { unsigned num_pixels = out_img->width * out_img->height; uint32_t *pixels = out_img->pixels; + for (i = 0; i < num_pixels; i++) { uint32_t col = pixels[i]; @@ -223,8 +150,6 @@ bool texture_image_load_argb_shift(const char *path, struct texture_image *out_i return false; } -#endif - #ifdef GEKKO #define GX_BLIT_LINE_32(off) \ @@ -245,7 +170,7 @@ bool texture_image_load_argb_shift(const char *path, struct texture_image *out_i src += tmp_pitch; \ } -static bool gx_convert_texture32(struct texture_image *image) +static bool rpng_gx_convert_texture32(struct texture_image *image) { // memory allocation in libogc is extremely primitive so try to avoid gaps in memory when converting // by copying over to temp buffer first then converting over into main buffer again @@ -279,21 +204,32 @@ static bool gx_convert_texture32(struct texture_image *image) #endif -bool texture_image_load(const char *path, struct texture_image *out_img) +static void rpng_image_free(void *data, void *image_data) { + struct texture_image *img = (struct texture_image*)image_data; + + free(img->pixels); + memset(img, 0, sizeof(*img)); +} + +static bool rpng_image_load(void *data, const char *path, void *image_data) +{ + (void)data; bool ret; + struct texture_image *out_img = (struct texture_image*)image_data; + // This interface "leak" is very ugly. FIXME: Fix this properly ... if (driver.gfx_use_rgba) - ret = texture_image_load_argb_shift(path, out_img, 24, 0, 8, 16); + ret = rpng_image_load_argb_shift(path, out_img, 24, 0, 8, 16); else - ret = texture_image_load_argb_shift(path, out_img, 24, 16, 8, 0); + ret = rpng_image_load_argb_shift(path, out_img, 24, 16, 8, 0); #ifdef GEKKO if (ret) { - if (!gx_convert_texture32(out_img)) + if (!rpng_gx_convert_texture32(out_img)) { - texture_image_free(out_img); + rpng_image_free(data, out_img); ret = false; } } @@ -302,9 +238,8 @@ bool texture_image_load(const char *path, struct texture_image *out_img) return ret; } -void texture_image_free(struct texture_image *img) -{ - free(img->pixels); - memset(img, 0, sizeof(*img)); -} - +const image_ctx_driver_t image_ctx_rpng = { + rpng_image_load, + rpng_image_free, + "rpng", +}; diff --git a/gfx/image/image_sdl.c b/gfx/image/image_sdl.c new file mode 100644 index 0000000000..d8a08a18cf --- /dev/null +++ b/gfx/image/image_sdl.c @@ -0,0 +1,135 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * + * 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 . + */ + +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif + +#include "../image_context.h" +#include "../../file.h" + +#include +#include +#include +#include "../../general.h" +#include "../rpng/rpng.h" + +#include "SDL_image.h" + +static bool sdl_load_argb_shift(const char *path, struct texture_image *out_img, + unsigned a_shift, unsigned r_shift, unsigned g_shift, unsigned b_shift) +{ + int y, x; + size_t size; + SDL_PixelFormat *fmt; + SDL_Surface *img = (SDL_Surface*)IMG_Load(path); + if (!img) + return false; + + out_img->width = img->w; + out_img->height = img->h; + + size = out_img->width * out_img->height * sizeof(uint32_t); + out_img->pixels = (uint32_t*)malloc(size); + + if (!out_img->pixels) + { + SDL_FreeSurface(img); + return false; + } + + fmt = (SDL_PixelFormat*)img->format; + + RARCH_LOG("SDL_image: %dx%d @ %d bpp\n", img->w, img->h, img->format->BitsPerPixel); + + if (img->format->BitsPerPixel == 32) + { + for (y = 0; y < img->h; y++) + { + uint32_t *dst = (uint32_t*)(out_img->pixels + y * img->w); + const uint32_t *src = (const uint32_t*)(img->pixels + y * img->pitch / sizeof(uint32_t)); + + for (x = 0; x < img->w; x++) + { + uint32_t r = (src[x] & fmt->Rmask) >> fmt->Rshift; + uint32_t g = (src[x] & fmt->Gmask) >> fmt->Gshift; + uint32_t b = (src[x] & fmt->Bmask) >> fmt->Bshift; + uint32_t a = (src[x] & fmt->Amask) >> fmt->Ashift; + dst[x] = (a << a_shift) | (r << r_shift) | (g << g_shift) | (b << b_shift); + } + } + } + else if (img->format->BitsPerPixel == 24) + { + for (y = 0; y < img->h; y++) + { + uint32_t *dst = (uint32_t*)(out_img->pixels + y * img->w); + const uint8_t *src = (const uint8_t*)(img->pixels + y * img->pitch); + + for (x = 0; x < img->w; x++) + { + // Correct? + uint32_t color,r, g, b; + color = 0; + color |= src[3 * x + 0] << 0; + color |= src[3 * x + 1] << 8; + color |= src[3 * x + 2] << 16; + r = (color & fmt->Rmask) >> fmt->Rshift; + g = (color & fmt->Gmask) >> fmt->Gshift; + b = (color & fmt->Bmask) >> fmt->Bshift; + dst[x] = (0xff << a_shift) | (r << r_shift) | (g << g_shift) | (b << b_shift); + } + } + } + else + { + RARCH_ERR("8-bit and 16-bit image support are not implemented.\n"); + SDL_FreeSurface(img); + return false; + } + + SDL_FreeSurface(img); + + return true; +} + +static bool sdl_image_load(void *data, const char *path, void *image_data) +{ + bool ret; + (void)data; + struct texture_image *out_img = (struct texture_image*)image_data; + + // This interface "leak" is very ugly. FIXME: Fix this properly ... + + if (driver.gfx_use_rgba) + ret = sdl_load_argb_shift(path, out_img, 24, 0, 8, 16); + else + ret = sdl_load_argb_shift(path, out_img, 24, 16, 8, 0); + + return ret; +} + +static void sdl_image_free(void *data, void *image_data) +{ + struct texture_image *img = (struct texture_image*)image_data; + free(img->pixels); + memset(img, 0, sizeof(*img)); +} + +const image_ctx_driver_t image_ctx_sdl = { + sdl_image_load, + sdl_image_free, + "sdl", +}; diff --git a/gfx/image/image_xdk1.c b/gfx/image/image_xdk1.c index 480b228705..4759a7f26c 100644 --- a/gfx/image/image_xdk1.c +++ b/gfx/image/image_xdk1.c @@ -14,12 +14,13 @@ * If not, see . */ -#include "image.h" +#include "../image_context.h" #include "../../xdk/xdk_d3d.h" -bool texture_image_load(const char *path, struct texture_image *out_img) +static bool xdk_image_load(void *data, const char *path, void *image_data) { - d3d_video_t *d3d = (d3d_video_t*)driver.video_data; + d3d_video_t *d3d = (d3d_video_t*)data; + struct texture_image *out_img = (struct texture_image*)image_data; D3DXIMAGE_INFO m_imageInfo; @@ -54,11 +55,22 @@ bool texture_image_load(const char *path, struct texture_image *out_img) return true; } -void texture_image_free(struct texture_image *img) +static void xdk_image_free(void *data, void *image_data) { + struct texture_image *img = (struct texture_image*)image_data; + + if (!img) + return; + if (img->vertex_buf) img->vertex_buf->Release(); if (img->pixels) img->pixels->Release(); memset(img, 0, sizeof(*img)); } + +const image_ctx_driver_t image_ctx_xdk = { + xdk_image_load, + xdk_image_free, + "xdk", +}; diff --git a/gfx/image_context.c b/gfx/image_context.c new file mode 100644 index 0000000000..8afc85e34a --- /dev/null +++ b/gfx/image_context.c @@ -0,0 +1,92 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2014 - 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 "../general.h" +#include "gfx_context.h" +#include "../general.h" +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +static const image_ctx_driver_t *image_ctx_drivers[] = { +#if defined(__CELLOS_LV2__) + &image_ctx_ps3, +#endif +#if defined(_XBOX1) + &image_ctx_xdk1, +#endif + &image_ctx_rpng, +#if defined(HAVE_SDL_IMAGE) + &image_ctx_sdl, +#endif + NULL +}; + +static int find_image_driver_index(const char *driver) +{ + unsigned i; + for (i = 0; image_ctx_drivers[i]; i++) + if (strcasecmp(driver, image_ctx_drivers[i]->ident) == 0) + return i; + return -1; +} + +void find_image_driver(void) +{ + int i; + if (driver.image) + return; + + i = find_image_driver_index(g_settings.image.driver); + if (i >= 0) + driver.image = image_ctx_drivers[i]; + else + { + unsigned d; + RARCH_ERR("Couldn't find any image driver named \"%s\"\n", g_settings.image.driver); + RARCH_LOG_OUTPUT("Available image drivers are:\n"); + for (d = 0; image_ctx_drivers[d]; d++) + RARCH_LOG_OUTPUT("\t%s\n", image_ctx_drivers[d]->ident); + + rarch_fail(1, "find_image_driver()"); + } +} + +void find_prev_image_driver(void) +{ + int i = find_image_driver_index(g_settings.image.driver); + if (i > 0) + { + strlcpy(g_settings.image.driver, image_ctx_drivers[i - 1]->ident, sizeof(g_settings.image.driver)); + driver.image = (image_ctx_driver_t*)image_ctx_drivers[i - 1]; + } + else + RARCH_WARN("Couldn't find any previous image driver (current one: \"%s\").\n", g_settings.image.driver); +} + +void find_next_image_driver(void) +{ + int i = find_image_driver_index(g_settings.image.driver); + if (i >= 0 && image_ctx_drivers[i + 1]) + { + strlcpy(g_settings.image.driver, image_ctx_drivers[i + 1]->ident, sizeof(g_settings.image.driver)); + driver.image = (image_ctx_driver_t*)image_ctx_drivers[i + 1]; + } + else + RARCH_WARN("Couldn't find any next image driver (current one: \"%s\").\n", g_settings.image.driver); +} diff --git a/gfx/image/image.h b/gfx/image_context.h similarity index 60% rename from gfx/image/image.h rename to gfx/image_context.h index aee2bc7e1a..fb6f0d0d8d 100644 --- a/gfx/image/image.h +++ b/gfx/image_context.h @@ -13,15 +13,15 @@ * If not, see . */ -#ifndef __RARCH_IMAGE_H -#define __RARCH_IMAGE_H +#ifndef __RARCH_IMAGE_CONTEXT_H +#define __RARCH_IMAGE_CONTEXT_H #include -#include "../../boolean.h" +#include "../boolean.h" #ifdef _XBOX1 #include -#include "../../xdk/xdk_defines.h" +#include "../xdk/xdk_defines.h" #endif struct texture_image @@ -38,8 +38,22 @@ struct texture_image #endif }; -bool texture_image_load(const char *path, struct texture_image* img); -void texture_image_free(struct texture_image *img); +typedef struct image_ctx_driver +{ + bool (*load)(void*, const char*, void *); + void (*free)(void *, void *); + // Human readable string. + const char *ident; +} image_ctx_driver_t; + +extern const image_ctx_driver_t image_ctx_xdk1; +extern const image_ctx_driver_t image_ctx_ps3; +extern const image_ctx_driver_t image_ctx_sdl; +extern const image_ctx_driver_t image_ctx_rpng; + +const void *image_ctx_find_driver(const char *ident); +void find_prev_image_driver(void); +void find_next_image_driver(void); +const void *image_ctx_init_first(void); #endif - diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c index 75c394d6ad..6b724b7417 100644 --- a/gfx/shader_cg.c +++ b/gfx/shader_cg.c @@ -26,7 +26,6 @@ #include #include "../compat/strl.h" #include "../conf/config_file.h" -#include "image/image.h" #include "../dynamic.h" #include "../compat/posix_string.h" #include "../file.h" diff --git a/gfx/shader_common.c b/gfx/shader_common.c index 4ef590f9fc..72f9663dc5 100644 --- a/gfx/shader_common.c +++ b/gfx/shader_common.c @@ -63,10 +63,17 @@ bool gl_load_luts(const struct gfx_shader *generic_shader, GLuint *lut_textures) glGenTextures(num_luts, lut_textures); for (i = 0; i < num_luts; i++) { + bool ret = false; struct texture_image img = {0}; RARCH_LOG("Loading texture image from: \"%s\" ...\n", generic_shader->lut[i].path); - if (!texture_image_load(generic_shader->lut[i].path, &img)) + + ret = driver.image && driver.image->load; + + if (ret) + ret = driver.image->load(driver.video_data, generic_shader->lut[i].path, &img); + + if (!ret) { RARCH_ERR("Failed to load texture image from: \"%s\"\n", generic_shader->lut[i].path); return false; @@ -76,7 +83,9 @@ bool gl_load_luts(const struct gfx_shader *generic_shader, GLuint *lut_textures) gl_wrap_type_to_enum(generic_shader->lut[i].wrap), generic_shader->lut[i].filter != RARCH_FILTER_NEAREST, generic_shader->lut[i].mipmap); - texture_image_free(&img); + + if (driver.image && driver.image->free) + driver.image->free(driver.video_data, &img); } glBindTexture(GL_TEXTURE_2D, 0); diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index 75a98c2775..d8a5e6e75e 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -33,7 +33,6 @@ #include #include "gl_common.h" -#include "image/image.h" #ifdef HAVE_OPENGLES2 #define BORDER_FUNC GL_CLAMP_TO_EDGE diff --git a/griffin/griffin.c b/griffin/griffin.c index 43e1ac7e07..d67ebb175f 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -172,13 +172,13 @@ VIDEO IMAGE #include "../gfx/image/image_ps3.c" #elif defined(_XBOX1) #include "../gfx/image/image_xdk1.c" -#else -#include "../gfx/image/image.c" +#elif defined(HAVE_SDL_IMAGE) +#include "../gfx/image/image_sdl.c" #endif -#if defined(WANT_RPNG) || defined(RARCH_MOBILE) +#include "../gfx/image_context.c" +#include "../gfx/image/image_rpng.c" #include "../gfx/rpng/rpng.c" -#endif /*============================================================ VIDEO DRIVER diff --git a/input/overlay.c b/input/overlay.c index ddb1b1754f..a6291ecd51 100644 --- a/input/overlay.c +++ b/input/overlay.c @@ -17,7 +17,7 @@ #include "../general.h" #include "../driver.h" #include "../libretro.h" -#include "../gfx/image/image.h" +#include "../gfx/image_context.h" #include "../conf/config_file.h" #include "../compat/posix_string.h" #include "input_common.h" @@ -162,11 +162,16 @@ void input_overlay_set_scale_factor(input_overlay_t *ol, float scale) static void input_overlay_free_overlay(struct overlay *overlay) { size_t i; - for (i = 0; i < overlay->size; i++) - texture_image_free(&overlay->descs[i].image); + + if (driver.image && driver.image->free) + for (i = 0; i < overlay->size; i++) + driver.image->free(driver.video_data, &overlay->descs[i].image); + free(overlay->load_images); free(overlay->descs); - texture_image_free(&overlay->image); + + if (driver.image && driver.image->free) + driver.image->free(driver.video_data, &overlay->image); } static void input_overlay_free_overlays(input_overlay_t *ol) @@ -197,8 +202,9 @@ static bool input_overlay_load_desc(input_overlay_t *ol, config_file_t *conf, st fill_pathname_resolve_relative(path, ol->overlay_path, image_path, sizeof(path)); struct texture_image img = {0}; - if (texture_image_load(path, &img)) - desc->image = img; + if (driver.image && driver.image->load) + if (driver.image->load(driver.video_data, path, &img)) + desc->image = img; } char overlay_desc_normalized_key[64]; @@ -345,13 +351,22 @@ static bool input_overlay_load_overlay(input_overlay_t *ol, config_file_t *conf, snprintf(overlay_path_key, sizeof(overlay_path_key), "overlay%u_overlay", index); if (config_get_path(conf, overlay_path_key, overlay_path, sizeof(overlay_path))) { + struct texture_image img = {0}; + bool ret = false; + fill_pathname_resolve_relative(overlay_resolved_path, config_path, overlay_path, sizeof(overlay_resolved_path)); - struct texture_image img = {0}; - if (texture_image_load(overlay_resolved_path, &img)) - overlay->image = img; - else + ret = driver.image && driver.image->load; + + if (ret) + { + ret = driver.image->load(driver.video_data, overlay_resolved_path, &img); + if(ret) + overlay->image = img; + } + + if (!ret) { RARCH_ERR("[Overlay]: Failed to load image: %s.\n", overlay_resolved_path); return false; diff --git a/retroarch.cfg b/retroarch.cfg index 06d2a4f9dd..af40b17ee8 100644 --- a/retroarch.cfg +++ b/retroarch.cfg @@ -77,6 +77,9 @@ # Load up a specific config file based on the core being used. # core_specific_config = false +# Image driver to use. "rpng", "sdl" +# image_driver = "rpng" + #### Video # Video driver to use. "gl", "xvideo", "sdl" diff --git a/settings.c b/settings.c index a7c7b77174..fe812b3ea7 100644 --- a/settings.c +++ b/settings.c @@ -202,11 +202,28 @@ const char *config_get_default_location(void) } #endif +const char *config_get_default_image(void) +{ + switch (IMAGE_DEFAULT_DRIVER) + { + case IMAGE_SDL: + return "sdl"; + case IMAGE_XDK: + return "xdk"; + case IMAGE_PS3: + return "ps3"; + case IMAGE_RPNG: + return "rpng"; + default: + return NULL; + } +} void config_set_defaults(void) { unsigned i, j; const char *def_video = config_get_default_video(); + const char *def_image = config_get_default_image(); const char *def_audio = config_get_default_audio(); const char *def_input = config_get_default_input(); #ifdef HAVE_CAMERA @@ -235,6 +252,8 @@ void config_set_defaults(void) strlcpy(g_settings.audio.driver, def_audio, sizeof(g_settings.audio.driver)); if (def_input) strlcpy(g_settings.input.driver, def_input, sizeof(g_settings.input.driver)); + if (def_image) + strlcpy(g_settings.image.driver, def_image, sizeof(g_settings.image.driver)); g_settings.load_dummy_on_core_shutdown = load_dummy_on_core_shutdown; @@ -947,6 +966,7 @@ bool config_load_file(const char *path, bool set_defaults) CONFIG_GET_BOOL(location.allow, "location_allow"); #endif + CONFIG_GET_STRING(image.driver, "image_driver"); CONFIG_GET_STRING(video.driver, "video_driver"); CONFIG_GET_STRING(video.gl_context, "video_gl_context"); CONFIG_GET_STRING(audio.driver, "audio_driver"); @@ -1331,6 +1351,7 @@ bool config_save_file(const char *path) config_set_int(conf, "video_fullscreen_x", g_settings.video.fullscreen_x); config_set_int(conf, "video_fullscreen_y", g_settings.video.fullscreen_y); config_set_string(conf,"video_driver", g_settings.video.driver); + config_set_string(conf,"image_driver", g_settings.image.driver); config_set_bool(conf, "video_vsync", g_settings.video.vsync); config_set_bool(conf, "video_hard_sync", g_settings.video.hard_sync); config_set_int(conf, "video_hard_sync_frames", g_settings.video.hard_sync_frames); diff --git a/xdk/xdk_d3d.h b/xdk/xdk_d3d.h index 86032ab8cb..6b486edd1a 100644 --- a/xdk/xdk_d3d.h +++ b/xdk/xdk_d3d.h @@ -23,7 +23,7 @@ #endif #include "../gfx/shader_common.h" #include "../gfx/shader_parse.h" -#include "../gfx/image/image.h" +#include "../gfx/image_context.h" #include "../gfx/fonts/d3d_font.h" #include "../gfx/gfx_context.h"