mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-09-10 12:02:53 +02:00
Implement image loading in libretro builds
This commit is contained in:
parent
8ed8dd14ee
commit
9f33a0acea
9 changed files with 110 additions and 115 deletions
13
meson.build
13
meson.build
|
@ -435,18 +435,6 @@ if is_libretro
|
|||
'CMAKE_BUILD_TYPE': 'None',
|
||||
})
|
||||
|
||||
libpng_options = cmake.subproject_options()
|
||||
libpng_options.add_cmake_defines({
|
||||
'CMAKE_C_FLAGS': ' '.join(libretro_defines + libretro_cflags),
|
||||
'CMAKE_CXX_FLAGS': ' '.join(libretro_defines + libretro_cppflags),
|
||||
'CMAKE_POSITION_INDEPENDENT_CODE': use_pic,
|
||||
'PNG_STATIC': true,
|
||||
'PNG_SHARED': false,
|
||||
'PNG_FRAMEWORK': false,
|
||||
'PNG_TESTS': false,
|
||||
'PNG_TOOLS': false,
|
||||
})
|
||||
|
||||
libretro_deps = [
|
||||
cmake.subproject('boost_asio', options: boost_options).dependency('boost_asio'),
|
||||
cmake.subproject('boost_mp11', options: boost_options).dependency('boost_mp11'),
|
||||
|
@ -473,7 +461,6 @@ if is_libretro
|
|||
cmake.subproject('mpg123', options: mpg123_options).dependency('libmpg123'),
|
||||
cmake.subproject('libsndfile', options: libsndfile_options).dependency('sndfile'),
|
||||
cmake.subproject('pixman-region', options: pixman_region_options).dependency('pixman-region'),
|
||||
cmake.subproject('libpng', options: libpng_options).dependency('png_static'),
|
||||
subproject('stb').get_variable('stb'),
|
||||
subproject('portablegl').get_variable('portablegl'),
|
||||
]
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "bitmap.h"
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
# include "stb_image_malloc.h"
|
||||
# include <stb_image.h>
|
||||
# include <pixman-region/pixman-region.h>
|
||||
#else
|
||||
# include <SDL.h>
|
||||
|
@ -435,6 +437,7 @@ struct BitmapPrivate
|
|||
if (surface && freeSurface)
|
||||
{
|
||||
#ifdef MKXPZ_RETRO
|
||||
stbi_image_free(surface->pixels);
|
||||
delete surface;
|
||||
#else
|
||||
SDL_FreeSurface(surface);
|
||||
|
@ -446,9 +449,52 @@ struct BitmapPrivate
|
|||
}
|
||||
};
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
struct BitmapOpenHandler : FileSystem::OpenHandler
|
||||
{
|
||||
#ifdef MKXPZ_RETRO
|
||||
// Non-GIF
|
||||
stbi_uc *image;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
BitmapOpenHandler()
|
||||
: image(NULL)
|
||||
{}
|
||||
|
||||
bool tryRead(std::shared_ptr<struct FileSystem::File> ops, const char *ext)
|
||||
{
|
||||
struct file {
|
||||
struct FileSystem::File *handle;
|
||||
uint64_t offset;
|
||||
};
|
||||
|
||||
const static stbi_io_callbacks callbacks = {
|
||||
.read = [](void *handle, char *buf, int size) {
|
||||
assert(size >= 0);
|
||||
int n = PHYSFS_readBytes(((struct file *)handle)->handle->get(), buf, size);
|
||||
assert(((struct file *)handle)->offset + (uint64_t)n >= ((struct file *)handle)->offset);
|
||||
((struct file *)handle)->offset += n;
|
||||
return n;
|
||||
},
|
||||
.skip = [](void *handle, int size) {
|
||||
assert(size >= 0);
|
||||
assert(((struct file *)handle)->offset + (uint64_t)size >= ((struct file *)handle)->offset);
|
||||
PHYSFS_seek(((struct file *)handle)->handle->get(), (((struct file *)handle)->offset += (uint64_t)size));
|
||||
},
|
||||
.eof = [](void *handle) {
|
||||
return PHYSFS_eof(((struct file *)handle)->handle->get());
|
||||
},
|
||||
};
|
||||
|
||||
struct file file {
|
||||
.handle = ops.get(),
|
||||
.offset = 0,
|
||||
};
|
||||
image = stbi_load_from_callbacks(&callbacks, &file, &width, &height, NULL, STBI_rgb_alpha);
|
||||
return image != NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
// Non-GIF
|
||||
SDL_Surface *surface;
|
||||
|
||||
|
@ -512,8 +558,8 @@ struct BitmapOpenHandler : FileSystem::OpenHandler
|
|||
}
|
||||
return (surface || gif);
|
||||
}
|
||||
};
|
||||
#endif // MKXPZ_RETRO
|
||||
};
|
||||
|
||||
Bitmap::Bitmap(const char *filename)
|
||||
{
|
||||
|
@ -535,11 +581,23 @@ Bitmap::Bitmap(const char *filename)
|
|||
hiresBitmap = nullptr;
|
||||
}
|
||||
}
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
BitmapOpenHandler handler;
|
||||
try {
|
||||
#ifdef MKXPZ_RETRO
|
||||
std::string path("/mkxp-retro-game/");
|
||||
path.append(filename);
|
||||
mkxp_retro::fs->openRead(handler, path.c_str()); // TODO: move into shState
|
||||
#else
|
||||
shState->fileSystem().openRead(handler, filename);
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
if (handler.image == NULL) {
|
||||
throw Exception(Exception::SDLError, "Error loading image '%s': %s", filename, stbi_failure_reason());
|
||||
}
|
||||
#else
|
||||
if (!handler.error.empty()) {
|
||||
// Not loaded with SDL, but I want it to be caught with the same exception type
|
||||
throw Exception(Exception::SDLError, "Error loading image '%s': %s", filename, handler.error.c_str());
|
||||
|
@ -548,12 +606,14 @@ Bitmap::Bitmap(const char *filename)
|
|||
throw Exception(Exception::SDLError, "Error loading image '%s': %s",
|
||||
filename, SDL_GetError());
|
||||
}
|
||||
#endif // MKXPZ_RETRO
|
||||
} catch (const Exception &e) {
|
||||
if (hiresBitmap)
|
||||
delete hiresBitmap;
|
||||
throw e;
|
||||
}
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
if (handler.gif) {
|
||||
if (handler.gif->width >= (uint32_t)glState.caps.maxTexSize || handler.gif->height > (uint32_t)glState.caps.maxTexSize)
|
||||
{
|
||||
|
@ -662,9 +722,9 @@ Bitmap::Bitmap(const char *filename)
|
|||
|
||||
#ifdef MKXPZ_RETRO
|
||||
SDL_Surface *imgSurf = new SDL_Surface;
|
||||
// TODO: use actual image dimensions
|
||||
imgSurf->w = 64;
|
||||
imgSurf->h = 64;
|
||||
imgSurf->pixels = handler.image;
|
||||
imgSurf->w = handler.width;
|
||||
imgSurf->h = handler.height;
|
||||
#endif // MKXPZ_RETRO
|
||||
initFromSurface(imgSurf, hiresBitmap, false);
|
||||
}
|
||||
|
@ -708,7 +768,17 @@ Bitmap::Bitmap(int width, int height, bool isHires)
|
|||
|
||||
Bitmap::Bitmap(void *pixeldata, int width, int height)
|
||||
{
|
||||
#ifndef MKXPZ_RETRO
|
||||
#ifdef MKXPZ_RETRO
|
||||
SDL_Surface *surface = new SDL_Surface;
|
||||
|
||||
stbi_uc *image = (stbi_uc *)STBI_MALLOC((size_t)4 * (size_t)width * (size_t)height * sizeof(stbi_uc));
|
||||
if (image == NULL)
|
||||
throw std::bad_alloc();
|
||||
|
||||
surface->pixels = image;
|
||||
surface->w = width;
|
||||
surface->h = height;
|
||||
#else
|
||||
SDL_Surface *surface = SDL_CreateRGBSurface(0, width, height, p->format->BitsPerPixel,
|
||||
p->format->Rmask,
|
||||
p->format->Gmask,
|
||||
|
@ -720,29 +790,30 @@ Bitmap::Bitmap(void *pixeldata, int width, int height)
|
|||
SDL_GetError());
|
||||
|
||||
memcpy(surface->pixels, pixeldata, width*height*(p->format->BitsPerPixel/8));
|
||||
#endif // MKXPZ_RERTRO
|
||||
|
||||
if (surface->w > glState.caps.maxTexSize || surface->h > glState.caps.maxTexSize)
|
||||
{
|
||||
p = new BitmapPrivate(this);
|
||||
p->megaSurface = surface;
|
||||
#ifndef MKXPZ_RETRO
|
||||
SDL_SetSurfaceBlendMode(p->megaSurface, SDL_BLENDMODE_NONE);
|
||||
#endif // MKXPZ_RETRO
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif // MKXPZ_RETRO
|
||||
TEXFBO tex;
|
||||
|
||||
try
|
||||
{
|
||||
#ifdef MKXPZ_RETRO
|
||||
tex = shState->texPool().request(64, 64); // TODO: use actual image dimensions
|
||||
#else
|
||||
tex = shState->texPool().request(surface->w, surface->h);
|
||||
#endif // MKXPZ_RETRO
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
#ifndef MKXPZ_RETRO
|
||||
#ifdef MKXPZ_RETRO
|
||||
stbi_image_free(surface->pixels);
|
||||
delete surface;
|
||||
#else
|
||||
SDL_FreeSurface(surface);
|
||||
#endif // MKXPZ_RETRO
|
||||
throw e;
|
||||
|
@ -752,12 +823,15 @@ Bitmap::Bitmap(void *pixeldata, int width, int height)
|
|||
p->gl = tex;
|
||||
|
||||
TEX::bind(p->gl.tex);
|
||||
#ifndef MKXPZ_RETRO
|
||||
TEX::uploadImage(p->gl.width, p->gl.height, surface->pixels, GL_RGBA);
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
stbi_image_free(surface->pixels);
|
||||
delete surface;
|
||||
#else
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
#endif // MKXPZ_RETRO
|
||||
}
|
||||
|
||||
p->addTaintedArea(rect());
|
||||
}
|
||||
|
@ -913,6 +987,7 @@ void Bitmap::initFromSurface(SDL_Surface *imgSurf, Bitmap *hiresBitmap, bool for
|
|||
if (hiresBitmap)
|
||||
delete hiresBitmap;
|
||||
#ifdef MKXPZ_RETRO
|
||||
stbi_image_free(imgSurf->pixels);
|
||||
delete imgSurf;
|
||||
#else
|
||||
SDL_FreeSurface(imgSurf);
|
||||
|
@ -928,11 +1003,10 @@ void Bitmap::initFromSurface(SDL_Surface *imgSurf, Bitmap *hiresBitmap, bool for
|
|||
}
|
||||
|
||||
TEX::bind(p->gl.tex);
|
||||
#ifndef MKXPZ_RETRO
|
||||
TEX::uploadImage(p->gl.width, p->gl.height, imgSurf->pixels, GL_RGBA);
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
stbi_image_free(imgSurf->pixels);
|
||||
delete imgSurf;
|
||||
#else
|
||||
SDL_FreeSurface(imgSurf);
|
||||
|
@ -2515,7 +2589,10 @@ int Bitmap::addFrame(Bitmap &source, int position)
|
|||
|
||||
if (p->surface)
|
||||
#ifdef MKXPZ_RETRO
|
||||
{
|
||||
stbi_image_free(p->surface->pixels);
|
||||
delete p->surface;
|
||||
}
|
||||
#else
|
||||
SDL_FreeSurface(p->surface);
|
||||
#endif // MKXPZ_RETRO
|
||||
|
@ -2526,6 +2603,7 @@ int Bitmap::addFrame(Bitmap &source, int position)
|
|||
TEX::bind(newframe.tex);
|
||||
TEX::uploadImage(source.width(), source.height(), source.surface()->pixels, GL_RGBA);
|
||||
#ifdef MKXPZ_RETRO
|
||||
stbi_image_free(p->surface->pixels);
|
||||
delete p->surface;
|
||||
#else
|
||||
SDL_FreeSurface(p->surface);
|
||||
|
@ -2729,7 +2807,10 @@ void Bitmap::releaseResources()
|
|||
|
||||
if (p->megaSurface)
|
||||
#ifdef MKXPZ_RETRO
|
||||
{
|
||||
stbi_image_free(p->megaSurface->pixels);
|
||||
delete p->megaSurface;
|
||||
}
|
||||
#else
|
||||
SDL_FreeSurface(p->megaSurface);
|
||||
#endif // MKXPZ_RETRO
|
||||
|
|
|
@ -514,9 +514,7 @@ public:
|
|||
const int w = geometry.rect.w;
|
||||
const int h = geometry.rect.h;
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
shState->prepareDraw();
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
pp.startRender();
|
||||
|
||||
|
|
|
@ -99,9 +99,7 @@ struct SpritePrivate
|
|||
|
||||
EtcTemps tmp;
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
sigslot::connection prepareCon;
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
SpritePrivate()
|
||||
: bitmap(0),
|
||||
|
@ -125,9 +123,7 @@ struct SpritePrivate
|
|||
|
||||
updateSrcRectCon();
|
||||
|
||||
#ifndef MKXPZ_RETRO
|
||||
prepareCon = shState->prepareDraw.connect
|
||||
#endif // MKXPZ_RETRO
|
||||
(&SpritePrivate::prepare, this);
|
||||
|
||||
patternScroll = Vec2(0,0);
|
||||
|
@ -143,9 +139,7 @@ struct SpritePrivate
|
|||
~SpritePrivate()
|
||||
{
|
||||
srcRectCon.disconnect();
|
||||
#ifndef MKXPZ_RETRO
|
||||
prepareCon.disconnect();
|
||||
#endif // MKXPZ_RETRO
|
||||
|
||||
bitmapDisposal();
|
||||
}
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
#include "stb_image_malloc.h"
|
||||
|
||||
#define STBI_NO_GIF
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
|
10
src/stb_image_malloc.h
Normal file
10
src/stb_image_malloc.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef MKXPZ_STB_IMAGE_MALLOC_H
|
||||
#define MKXPZ_STB_IMAGE_MALLOC_H
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#define STBI_MALLOC std::malloc
|
||||
#define STBI_REALLOC std::realloc
|
||||
#define STBI_FREE std::free
|
||||
|
||||
#endif // MKXPZ_STB_IMAGE_MALLOC_H
|
|
@ -1,5 +0,0 @@
|
|||
[wrap-git]
|
||||
url = https://github.com/pnggroup/libpng
|
||||
revision = v1.6.47
|
||||
depth = 1
|
||||
diff_files = libpng-awk.patch, libpng-deps.patch
|
|
@ -1,13 +0,0 @@
|
|||
# Prevents libpng's build system from using AWK.
|
||||
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -351,7 +351,7 @@ endif()
|
||||
# Find an AWK language processor.
|
||||
# Start with specific AWK implementations like gawk and nawk, which are
|
||||
# known to work with our scripts, then fall back to the system awk.
|
||||
-find_program(AWK NAMES gawk nawk awk)
|
||||
+
|
||||
if(AWK)
|
||||
message(STATUS "Found AWK program: ${AWK}")
|
||||
else()
|
|
@ -1,60 +0,0 @@
|
|||
# Prevents libpng's build system from trying to look for zlib externally since Meson already handles that.
|
||||
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -114,7 +114,7 @@ if(PNG_BUILD_ZLIB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
-find_package(ZLIB REQUIRED)
|
||||
+
|
||||
|
||||
if(UNIX
|
||||
AND NOT (APPLE OR BEOS OR HAIKU)
|
||||
@@ -628,7 +628,7 @@ if(PNG_SHARED)
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
|
||||
target_include_directories(png_shared SYSTEM
|
||||
INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/libpng${PNGLIB_ABI_VERSION}>)
|
||||
- target_link_libraries(png_shared PUBLIC ZLIB::ZLIB ${M_LIBRARY})
|
||||
+ target_link_libraries(png_shared PUBLIC ${M_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(PNG_STATIC)
|
||||
@@ -644,7 +644,7 @@ if(PNG_STATIC)
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
|
||||
target_include_directories(png_static SYSTEM
|
||||
INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/libpng${PNGLIB_ABI_VERSION}>)
|
||||
- target_link_libraries(png_static PUBLIC ZLIB::ZLIB ${M_LIBRARY})
|
||||
+ target_link_libraries(png_static PUBLIC ${M_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(PNG_FRAMEWORK AND NOT APPLE)
|
||||
@@ -675,7 +675,7 @@ if(PNG_FRAMEWORK)
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
|
||||
target_include_directories(png_framework SYSTEM
|
||||
INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/libpng${PNGLIB_ABI_VERSION}>)
|
||||
- target_link_libraries(png_framework PUBLIC ZLIB::ZLIB ${M_LIBRARY})
|
||||
+ target_link_libraries(png_framework PUBLIC ${M_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(NOT PNG_LIBRARY_TARGETS)
|
||||
@@ -864,7 +864,7 @@ if(PNG_SHARED AND PNG_TOOLS)
|
||||
set(PNG_BIN_TARGETS pngfix)
|
||||
|
||||
add_executable(png-fix-itxt ${png_fix_itxt_sources})
|
||||
- target_link_libraries(png-fix-itxt PRIVATE ZLIB::ZLIB ${M_LIBRARY})
|
||||
+ target_link_libraries(png-fix-itxt PRIVATE ${M_LIBRARY})
|
||||
list(APPEND PNG_BIN_TARGETS png-fix-itxt)
|
||||
endif()
|
||||
|
||||
--- a/pngstruct.h
|
||||
+++ b/pngstruct.h
|
||||
@@ -26,7 +26,7 @@
|
||||
/* We must ensure that zlib uses 'const' in declarations. */
|
||||
# define ZLIB_CONST
|
||||
#endif
|
||||
-#include "zlib.h"
|
||||
+#include "../zlib/zlib.h"
|
||||
#ifdef const
|
||||
/* zlib.h sometimes #defines const to nothing, undo this. */
|
||||
# undef const
|
Loading…
Add table
Reference in a new issue