Get Graphics::update() working (probably) in libretro builds

This commit is contained in:
刘皓 2025-02-19 18:16:08 -05:00
parent 540d5f1a1a
commit 20c8f6d463
No known key found for this signature in database
GPG key ID: 7901753DB465B711
8 changed files with 248 additions and 151 deletions

View file

@ -387,6 +387,7 @@ if is_libretro
'src/display/gl/texpool.cpp',
'src/display/gl/tileatlas.cpp',
'src/display/gl/vertex.cpp',
'src/display/graphics.cpp',
'src/etc/etc.cpp',
'src/etc/table.cpp',
'src/filesystem/filesystem.cpp',

View file

@ -35,7 +35,6 @@
#include "core.h"
#include "filesystem.h"
#include "gl-fun.h"
#include "gl-meta.h"
using namespace mkxp_retro;
using namespace mkxp_sandbox;
@ -381,10 +380,6 @@ extern "C" RETRO_API void retro_run() {
shared_state_initialized = true;
}
if (hw_render.context_type != RETRO_HW_CONTEXT_NONE) {
GLMeta::blitBeginScreen({640, 480});
}
if (mkxp_retro::sandbox.has_value()) {
try {
if (sb().run<struct main>()) {
@ -399,6 +394,10 @@ extern "C" RETRO_API void retro_run() {
}
}
if (mkxp_retro::sandbox.has_value()) {
shState->graphics().update();
}
void *fb;
if (hw_render.context_type != RETRO_HW_CONTEXT_NONE) {
fb = RETRO_HW_FRAME_BUFFER_VALID;
@ -415,10 +414,6 @@ extern "C" RETRO_API void retro_run() {
}
video_refresh(fb, 640, 480, 640 * 4);
if (hw_render.context_type != RETRO_HW_CONTEXT_NONE) {
GLMeta::blitEnd();
}
if (mkxp_retro::sandbox.has_value()) {
audio->render();
alcRenderSamplesSOFT(al_device, sound_buf, 735);

View file

@ -171,9 +171,7 @@ struct BitmapPrivate
bool playing;
bool needsReset;
bool loop;
#ifndef MKXPZ_RETRO
std::vector<TEXFBO> frames;
#endif // MKXPZ_RETRO
float fps;
int lastFrame;
double startTime, playTime;
@ -183,7 +181,6 @@ struct BitmapPrivate
return floor(lastFrame + (playTime / (1 / fps)));
}
#ifndef MKXPZ_RETRO
unsigned int currentFrameI() {
if (!playing || needsReset) return lastFrame;
int i = currentFrameIRaw();
@ -194,7 +191,6 @@ struct BitmapPrivate
int i = currentFrameI();
return frames[i];
}
#endif // MKXPZ_RETRO
inline void play() {
playing = true;
@ -202,23 +198,17 @@ struct BitmapPrivate
}
inline void stop() {
#ifndef MKXPZ_RETRO
lastFrame = currentFrameI();
#endif // MKXPZ_RETRO
playing = false;
}
inline void seek(int frame) {
#ifndef MKXPZ_RETRO
lastFrame = clamp(frame, 0, (int)frames.size());
#endif // MKXPZ_RETRO
}
void updateTimer() {
if (needsReset) {
#ifndef MKXPZ_RETRO
lastFrame = currentFrameI();
#endif // MKXPZ_RETRO
playTime = 0;
startTime = shState->runTime();
needsReset = false;
@ -303,11 +293,7 @@ struct BitmapPrivate
}
TEXFBO &getGLTypes() {
#ifdef MKXPZ_RETRO
return gl; // TODO
#else
return (animation.enabled) ? animation.currentFrame() : gl;
#endif // MKXPZ_RETRO
}
void prepare()
@ -388,14 +374,11 @@ struct BitmapPrivate
Debug() << "BUG: High-res BitmapPrivate bindTexture for animations not implemented";
}
#ifndef MKXPZ_RETRO
TEXFBO cframe = animation.currentFrame();
TEX::bind(cframe.tex);
shader.setTexSize(Vec2i(cframe.width, cframe.height));
#endif // MKXPZ_RETRO
return;
}
#ifndef MKXPZ_RETRO
TEX::bind(gl.tex);
if (selfLores && substituteLoresSize) {
shader.setTexSize(Vec2i(selfLores->width(), selfLores->height()));
@ -403,22 +386,17 @@ struct BitmapPrivate
else {
shader.setTexSize(Vec2i(gl.width, gl.height));
}
#endif // MKXPZ_RETRO
}
void bindFBO()
{
#ifndef MKXPZ_RETRO
FBO::bind((animation.enabled) ? animation.currentFrame().fbo : gl.fbo);
#endif // MKXPZ_RETRO
}
void pushSetViewport(ShaderBase &shader) const
{
#ifndef MKXPZ_RETRO
glState.viewport.pushSet(IntRect(0, 0, gl.width, gl.height));
shader.applyViewportProj();
#endif // MKXPZ_RETRO
}
void popViewport() const
@ -429,9 +407,7 @@ struct BitmapPrivate
void blitQuad(Quad &quad)
{
glState.blend.pushSet(false);
#ifndef MKXPZ_RETRO
quad.draw();
#endif // MKXPZ_RETRO
glState.blend.pop();
}
@ -440,7 +416,6 @@ struct BitmapPrivate
{
bindFBO();
#ifndef MKXPZ_RETRO
glState.scissorTest.pushSet(true);
glState.scissorBox.pushSet(normalizedRect(rect));
glState.clearColor.pushSet(color);
@ -450,7 +425,6 @@ struct BitmapPrivate
glState.clearColor.pop();
glState.scissorBox.pop();
glState.scissorTest.pop();
#endif // MKXPZ_RETRO
}
#ifndef MKXPZ_RETRO
@ -714,6 +688,7 @@ Bitmap::Bitmap(int width, int height, bool isHires)
hiresBitmap = new Bitmap(hiresWidth, hiresHeight, true);
hiresBitmap->setLores(this);
}
#endif // MKXPZ_RETRO
TEXFBO tex;
try {
@ -723,16 +698,13 @@ Bitmap::Bitmap(int width, int height, bool isHires)
delete hiresBitmap;
throw e;
}
#endif // MKXPZ_RETRO
p = new BitmapPrivate(this);
#ifndef MKXPZ_RETRO
p->gl = tex;
p->selfHires = hiresBitmap;
if (p->selfHires != nullptr) {
p->gl.selfHires = &p->selfHires->getGLTypes();
}
#endif // MKXPZ_RETRO
clear();
}
@ -802,7 +774,6 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
// TODO: Clean me up
if (!other.isAnimated() || frame >= -1) {
#ifndef MKXPZ_RETRO
try {
p->gl = shState->texPool().request(other.width(), other.height());
} catch (const Exception &e) {
@ -821,7 +792,6 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
}
GLMeta::blitRectangle(rect(), rect());
GLMeta::blitEnd();
#endif // MKXPZ_RETRO
}
else {
p->animation.enabled = true;
@ -833,7 +803,6 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
p->animation.startTime = 0;
p->animation.loop = other.getLooping();
#ifndef MKXPZ_RETRO
for (TEXFBO &sourceframe : other.getFrames()) {
TEXFBO newframe;
try {
@ -850,7 +819,6 @@ Bitmap::Bitmap(const Bitmap &other, int frame)
p->animation.frames.push_back(newframe);
}
#endif // MKXPZ_RETRO
}
p->addTaintedArea(rect());
@ -860,18 +828,15 @@ Bitmap::Bitmap(TEXFBO &other)
{
Bitmap *hiresBitmap = nullptr;
#ifndef MKXPZ_RETRO
if (other.selfHires != nullptr) {
// Create a high-res version as well.
hiresBitmap = new Bitmap(*other.selfHires);
hiresBitmap->setLores(this);
}
#endif // MKXPZ_RETRO
p = new BitmapPrivate(this);
p->selfHires = hiresBitmap;
#ifndef MKXPZ_RETRO
try {
p->gl = shState->texPool().request(other.width, other.height);
} catch (const Exception &e) {
@ -890,7 +855,6 @@ Bitmap::Bitmap(TEXFBO &other)
GLMeta::blitRectangle(rect(), rect());
GLMeta::blitEnd();
}
#endif // MKXPZ_RETRO
p->addTaintedArea(rect());
}
@ -919,6 +883,7 @@ void Bitmap::initFromSurface(SDL_Surface *imgSurf, Bitmap *hiresBitmap, bool for
{
#ifndef MKXPZ_RETRO
p->ensureFormat(imgSurf, SDL_PIXELFORMAT_ABGR8888);
#endif // MKXPZ_RETRO
if (imgSurf->w > glState.caps.maxTexSize || imgSurf->h > glState.caps.maxTexSize || forceMega)
{
@ -927,7 +892,9 @@ void Bitmap::initFromSurface(SDL_Surface *imgSurf, Bitmap *hiresBitmap, bool for
p = new BitmapPrivate(this);
p->selfHires = hiresBitmap;
p->megaSurface = imgSurf;
#ifndef MKXPZ_RETRO
SDL_SetSurfaceBlendMode(p->megaSurface, SDL_BLENDMODE_NONE);
#endif // MKXPZ_RETRO
}
else
{
@ -942,14 +909,14 @@ void Bitmap::initFromSurface(SDL_Surface *imgSurf, Bitmap *hiresBitmap, bool for
{
if (hiresBitmap)
delete hiresBitmap;
#ifndef MKXPZ_RETRO
SDL_FreeSurface(imgSurf);
#endif // MKXPZ_RETRO
throw e;
}
#endif // MKXPZ_RETRO
p = new BitmapPrivate(this);
p->selfHires = hiresBitmap;
#ifndef MKXPZ_RETRO
p->gl = tex;
if (p->selfHires != nullptr) {
p->gl.selfHires = &p->selfHires->getGLTypes();
@ -958,9 +925,10 @@ void Bitmap::initFromSurface(SDL_Surface *imgSurf, Bitmap *hiresBitmap, bool for
TEX::bind(p->gl.tex);
TEX::uploadImage(p->gl.width, p->gl.height, imgSurf->pixels, GL_RGBA);
#ifndef MKXPZ_RETRO
SDL_FreeSurface(imgSurf);
}
#endif // MKXPZ_RETRO
}
p->addTaintedArea(rect());
}
@ -969,9 +937,6 @@ int Bitmap::width() const
{
guardDisposed();
#ifdef MKXPZ_RETRO
return 32; // TODO: implement
#else
if (p->megaSurface) {
return p->megaSurface->w;
}
@ -981,16 +946,12 @@ int Bitmap::width() const
}
return p->gl.width;
#endif // MKXPZ_RETRO
}
int Bitmap::height() const
{
guardDisposed();
#ifdef MKXPZ_RETRO
return 32; // TODO: implement
#else
if (p->megaSurface)
return p->megaSurface->h;
@ -998,7 +959,6 @@ int Bitmap::height() const
return p->animation.height;
return p->gl.height;
#endif // MKXPZ_RETRO
}
bool Bitmap::hasHires() const{
@ -1479,7 +1439,6 @@ void Bitmap::gradientFillRect(const IntRect &rect,
p->selfHires->gradientFillRect(IntRect(destX, destY, destWidth, destHeight), color1, color2, vertical);
}
#ifndef MKXPZ_RETRO
SimpleColorShader &shader = shState->shaders().simpleColor;
shader.bind();
shader.setTranslation(Vec2i());
@ -1509,7 +1468,6 @@ void Bitmap::gradientFillRect(const IntRect &rect,
p->blitQuad(quad);
p->popViewport();
#endif // MKXPZ_RETRO
p->addTaintedArea(rect);
@ -1556,7 +1514,6 @@ void Bitmap::blur()
// TODO: Is there some kind of blur radius that we need to handle for high-res mode?
#ifndef MKXPZ_RETRO
Quad &quad = shState->gpQuad();
FloatRect rect(0, 0, width(), height());
quad.setTexPosRect(rect, rect);
@ -1592,7 +1549,6 @@ void Bitmap::blur()
glState.blend.pop();
shState->texPool().release(auxTex);
#endif // MKXPZ_RETRO
p->onModified();
}
@ -1619,7 +1575,6 @@ void Bitmap::radialBlur(int angle, int divisions)
float opacity = 1.0f / divisions;
float baseAngle = -((float) angle / 2);
#ifndef MKXPZ_RETRO
ColorQuadArray qArray;
qArray.resize(5);
@ -1696,7 +1651,6 @@ void Bitmap::radialBlur(int angle, int divisions)
shState->texPool().release(p->gl);
p->gl = newTex;
#endif // MKXPZ_RETRO
p->onModified();
}
@ -1713,20 +1667,17 @@ void Bitmap::clear()
p->bindFBO();
#ifndef MKXPZ_RETRO
glState.clearColor.pushSet(Vec4());
FBO::clear();
glState.clearColor.pop();
#endif // MKXPZ_RETRO
p->clearTaintedArea();
p->onModified();
}
#ifndef MKXPZ_RETRO
static uint32_t &getPixelAt(SDL_Surface *surf, SDL_PixelFormat *form, int x, int y)
{
size_t offset = x*form->BytesPerPixel + y*surf->pitch;
@ -1734,7 +1685,6 @@ static uint32_t &getPixelAt(SDL_Surface *surf, SDL_PixelFormat *form, int x, int
return *((uint32_t*) bytes);
}
#endif // MKXPZ_RETRO
Color Bitmap::getPixel(int x, int y) const
{
@ -1793,7 +1743,6 @@ Color Bitmap::getPixel(int x, int y) const
{
p->allocSurface();
#ifndef MKXPZ_RETRO
FBO::bind(p->gl.fbo);
glState.viewport.pushSet(IntRect(0, 0, width(), height()));
@ -1801,7 +1750,6 @@ Color Bitmap::getPixel(int x, int y) const
gl.ReadPixels(0, 0, width(), height(), GL_RGBA, GL_UNSIGNED_BYTE, p->surface->pixels);
glState.viewport.pop();
#endif // MKXPZ_RETRO
}
#ifdef MKXPZ_RETRO
@ -1849,10 +1797,8 @@ void Bitmap::setPixel(int x, int y, const Color &color)
(uint8_t) clamp<double>(color.alpha, 0, 255)
};
#ifndef MKXPZ_RETRO
TEX::bind(p->gl.tex);
TEX::uploadSubImage(x, y, 1, 1, &pixel, GL_RGBA);
#endif // MKXPZ_RETRO
p->addTaintedArea(IntRect(x, y, 1, 1));
@ -1880,18 +1826,14 @@ bool Bitmap::getRaw(void *output, int output_size)
Debug() << "GAME BUG: Game is calling getRaw on low-res Bitmap; you may want to patch the game to improve graphics quality.";
}
#ifndef MKXPZ_RETRO
if (!p->animation.enabled && (p->surface || p->megaSurface)) {
void *src = (p->megaSurface) ? p->megaSurface->pixels : p->surface->pixels;
memcpy(output, src, output_size);
}
else {
#endif // MKXPZ_RETRO
FBO::bind(getGLTypes().fbo);
gl.ReadPixels(0,0,width(),height(),GL_RGBA,GL_UNSIGNED_BYTE,output);
#ifndef MKXPZ_RETRO
}
#endif // MKXPZ_RETRO
return true;
}
@ -1998,7 +1940,6 @@ void Bitmap::hueChange(int hue)
if ((hue % 360) == 0)
return;
#ifndef MKXPZ_RETRO
TEXFBO newTex = shState->texPool().request(width(), height());
FloatRect texRect(rect());
@ -2024,7 +1965,6 @@ void Bitmap::hueChange(int hue)
shState->texPool().release(p->gl);
p->gl = newTex;
#endif // MKXPZ_RETRO
p->onModified();
}
@ -2051,7 +1991,6 @@ static std::string fixupString(const char *str)
return s;
}
#ifndef MKXPZ_RETRO
static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_Color &c)
{
SDL_Surface *out = SDL_CreateRGBSurface
@ -2138,7 +2077,6 @@ static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_C
SDL_FreeSurface(in);
in = out;
}
#endif // MKXPZ_RETRO
void Bitmap::drawText(const IntRect &rect, const char *str, int align)
{
@ -2169,7 +2107,6 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
return;
}
#endif // MKXPZ_RETRO
std::string fixed = fixupString(str);
str = fixed.c_str();
@ -2180,7 +2117,6 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
if (str[0] == ' ' && str[1] == '\0')
return;
#ifndef MKXPZ_RETRO
TTF_Font *font = p->font->getSdlFont();
const Color &fontColor = p->font->getColor();
const Color &outColor = p->font->getOutColor();
@ -2358,24 +2294,24 @@ DEF_ATTR_RD_SIMPLE(Bitmap, Font, Font&, *p->font)
void Bitmap::setFont(Font &value)
{
// High-res support handled in drawText, not here.
#ifndef MKXPZ_RETRO
// High-res support handled in drawText, not here.
*p->font = value;
#endif // MKXPZ_RETRO
}
void Bitmap::setInitFont(Font *value)
{
#ifndef MKXPZ_RETRO
if (hasHires()) {
Font *hiresFont = p->selfHires->p->font;
#ifndef MKXPZ_RETRO
if (hiresFont && hiresFont != &shState->defaultFont())
{
// Disable the illegal font size check when creating a high-res font.
hiresFont->setSize(hiresFont->getSize() * p->selfHires->width() / width(), false);
}
#endif // MKXPZ_RETRO
}
#endif // MKXPZ_RETRO
p->font = value;
}
@ -2474,11 +2410,7 @@ bool Bitmap::isPlaying() const
if (p->animation.loop)
return true;
#ifdef MKXPZ_RETRO
return false; // TODO: implement
#else
return p->animation.currentFrameIRaw() < p->animation.frames.size();
#endif // MKXPZ_RETRO
}
void Bitmap::gotoAndStop(int frame)
@ -2518,14 +2450,9 @@ int Bitmap::numFrames() const
}
if (!p->animation.enabled) return 1;
#ifdef MKXPZ_RETRO
return 0; // TODO: implement
#else
return (int)p->animation.frames.size();
#endif // MKXPZ_RETRO
}
#ifndef MKXPZ_RETRO
int Bitmap::currentFrameI() const
{
guardDisposed();
@ -2537,7 +2464,6 @@ int Bitmap::currentFrameI() const
if (!p->animation.enabled) return 0;
return p->animation.currentFrameI();
}
#endif // MKXPZ_RETRO
int Bitmap::addFrame(Bitmap &source, int position)
{
@ -2558,7 +2484,6 @@ int Bitmap::addFrame(Bitmap &source, int position)
throw Exception(Exception::MKXPError, "Animations with varying dimensions are not supported (%ix%i vs %ix%i)",
source.width(), source.height(), width(), height());
#ifndef MKXPZ_RETRO
TEXFBO newframe = shState->texPool().request(source.width(), source.height());
// Convert the bitmap into an animated bitmap if it isn't already one
@ -2571,19 +2496,27 @@ int Bitmap::addFrame(Bitmap &source, int position)
p->animation.startTime = 0;
if (p->animation.fps <= 0)
#ifdef MKXPZ_RETRO // TODO: use actual FPS
p->animation.fps = 60.0;
#else
p->animation.fps = shState->graphics().getFrameRate();
#endif // MKXPZ_RETRO
p->animation.frames.push_back(p->gl);
#ifndef MKXPZ_RETRO
if (p->surface)
SDL_FreeSurface(p->surface);
#endif // MKXPZ_RETRO
p->gl = TEXFBO();
}
if (source.surface()) {
TEX::bind(newframe.tex);
TEX::uploadImage(source.width(), source.height(), source.surface()->pixels, GL_RGBA);
#ifndef MKXPZ_RETRO
SDL_FreeSurface(p->surface);
#endif // MKXPZ_RETRO
p->surface = 0;
}
else {
@ -2593,23 +2526,14 @@ int Bitmap::addFrame(Bitmap &source, int position)
GLMeta::blitEnd();
}
#endif // MKXPZ_RETRO
int ret;
if (position < 0) {
#ifndef MKXPZ_RETRO
p->animation.frames.push_back(newframe);
#endif // MKXPZ_RETRO
#ifdef MKXPZ_RETRO
ret = 0; // TODO: implement
#else
ret = (int)p->animation.frames.size();
#endif // MKXPZ_RETRO
}
else {
#ifndef MKXPZ_RETRO
p->animation.frames.insert(p->animation.frames.begin() + clamp(position, 0, (int)p->animation.frames.size()), newframe);
#endif // MKXPZ_RETRO
ret = position;
}
@ -2625,7 +2549,6 @@ void Bitmap::removeFrame(int position) {
Debug() << "BUG: High-res Bitmap removeFrame not implemented";
}
#ifndef MKXPZ_RETRO
int pos = (position < 0) ? (int)p->animation.frames.size() - 1 : clamp(position, 0, (int)(p->animation.frames.size() - 1));
shState->texPool().release(p->animation.frames[pos]);
p->animation.frames.erase(p->animation.frames.begin() + pos);
@ -2645,7 +2568,6 @@ void Bitmap::removeFrame(int position) {
FBO::bind(p->gl.fbo);
taintArea(rect());
}
#endif // MKXPZ_RETRO
}
void Bitmap::nextFrame()
@ -2659,13 +2581,11 @@ void Bitmap::nextFrame()
}
stop();
#ifndef MKXPZ_RETRO
if ((uint32_t)p->animation.lastFrame >= p->animation.frames.size() - 1) {
if (!p->animation.loop) return;
p->animation.lastFrame = 0;
return;
}
#endif // MKXPZ_RETRO
p->animation.lastFrame++;
}
@ -2686,9 +2606,7 @@ void Bitmap::previousFrame()
p->animation.lastFrame = 0;
return;
}
#ifndef MKXPZ_RETRO
p->animation.lastFrame = (int)p->animation.frames.size() - 1;
#endif // MKXPZ_RETRO
return;
}
@ -2711,7 +2629,6 @@ void Bitmap::setAnimationFPS(float FPS)
if (restart) p->animation.play();
}
#ifndef MKXPZ_RETRO
std::vector<TEXFBO> &Bitmap::getFrames() const
{
if (hasHires()) {
@ -2720,7 +2637,6 @@ std::vector<TEXFBO> &Bitmap::getFrames() const
return p->animation.frames;
}
#endif // MKXPZ_RETRO
float Bitmap::getAnimationFPS() const
{
@ -2783,11 +2699,9 @@ void Bitmap::taintArea(const IntRect &rect)
p->addTaintedArea(rect);
}
#ifndef MKXPZ_RETRO
int Bitmap::maxSize(){
return glState.caps.maxTexSize;
}
#endif // MKXPZ_RETRO
void Bitmap::assumeRubyGC()
{
@ -2803,7 +2717,9 @@ void Bitmap::releaseResources()
#ifndef MKXPZ_RETRO
if (p->megaSurface)
SDL_FreeSurface(p->megaSurface);
else if (p->animation.enabled) {
else
#endif // MKXPZ_RETRO
if (p->animation.enabled) {
p->animation.enabled = false;
p->animation.playing = false;
for (TEXFBO &tex : p->animation.frames)
@ -2811,7 +2727,6 @@ void Bitmap::releaseResources()
}
else
shState->texPool().release(p->gl);
#endif // MKXPZ_RETRO
delete p;
}

View file

@ -211,14 +211,10 @@ int smoothScalingMethod(int scaleIsSpecial)
static void _blitBegin(FBO::ID fbo, const Vec2i &size, int scaleIsSpecial)
{
if (HAVE_NATIVE_BLIT)
FBO::bind(fbo);
if (!HAVE_NATIVE_BLIT)
{
FBO::boundFramebufferID = fbo;
gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo.gl);
}
else
{
FBO::bind(fbo);
glState.viewport.pushSet(IntRect(0, 0, size.x, size.y));
switch (smoothScalingMethod(scaleIsSpecial))
@ -303,15 +299,7 @@ void blitBeginScreen(const Vec2i &size, int scaleIsSpecial)
blitDstHeightLores = 1;
blitDstHeightHires = 1;
_blitBegin(
#ifdef MKXPZ_RETRO
FBO::ID(mkxp_retro::hw_render.get_current_framebuffer()),
#else
FBO::ID(0),
#endif // MKXPZ_RETRO
size,
scaleIsSpecial
);
_blitBegin(FBO::ID(0), size, scaleIsSpecial);
}
void blitSource(TEXFBO &source, int scaleIsSpecial)
@ -329,7 +317,14 @@ void blitSource(TEXFBO &source, int scaleIsSpecial)
if (HAVE_NATIVE_BLIT)
{
gl.BindFramebuffer(GL_READ_FRAMEBUFFER, source.fbo.gl);
gl.BindFramebuffer(
GL_READ_FRAMEBUFFER,
#ifdef MKXPZ_RETRO
source.fbo.gl || mkxp_retro::hw_render.get_current_framebuffer()
#else
source.fbo.gl
#endif // MKXPZ_RETRO
);
}
else
{

View file

@ -26,6 +26,9 @@
#include "etc-internal.h"
#include "sharedstate.h"
#include "config.h"
#ifdef MKXPZ_RETRO
# include "core.h"
#endif // MKXPZ_RETRO
/* Struct wrapping GLuint for some light type safety */
#define DEF_GL_ID \
@ -139,7 +142,14 @@ namespace FBO
static inline void bind(ID id)
{
boundFramebufferID = id;
gl.BindFramebuffer(GL_FRAMEBUFFER, id.gl);
gl.BindFramebuffer(
GL_FRAMEBUFFER,
#ifdef MKXPZ_RETRO
id.gl || mkxp_retro::hw_render.get_current_framebuffer()
#else
id.gl
#endif // MKXPZ_RETRO
);
}
static inline void unbind()

View file

@ -41,17 +41,21 @@
#include "shader.h"
#include "sharedstate.h"
#include "texpool.h"
#include "theoraplay/theoraplay.h"
#ifndef MKXPZ_RETRO
# include "theoraplay/theoraplay.h"
#endif // MKXPZ_RETRO
#include "util.h"
#include "input.h"
#include "sprite.h"
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_timer.h>
#include <SDL_video.h>
#include <SDL_mutex.h>
#include <SDL_thread.h>
#ifndef MKXPZ_RETRO
# include <SDL.h>
# include <SDL_image.h>
# include <SDL_timer.h>
# include <SDL_video.h>
# include <SDL_mutex.h>
# include <SDL_thread.h>
#endif // MKXPZ_RETRO
#ifdef MKXPZ_STEAM
#include "steamshim_child.h"
@ -76,6 +80,7 @@
#define MOVIE_AUDIO_BUFFER_SIZE 2048
#define AUDIO_BUFFER_LEN_MS 2000
#ifndef MKXPZ_RETRO
typedef struct AudioQueue
{
const THEORAPLAY_AudioPacket *audio;
@ -437,6 +442,7 @@ struct MovieOpenHandler : FileSystem::OpenHandler
return true;
}
};
#endif // MKXPZ_RETRO
struct PingPong {
TEXFBO rt[2];
@ -508,7 +514,9 @@ public:
const int w = geometry.rect.w;
const int h = geometry.rect.h;
#ifndef MKXPZ_RETRO
shState->prepareDraw();
#endif // MKXPZ_RETRO
pp.startRender();
@ -665,6 +673,7 @@ private:
/* Nanoseconds per second */
#define NS_PER_S 1000000000
#ifndef MKXPZ_RETRO
struct FPSLimiter {
uint64_t lastTickCount;
@ -774,6 +783,7 @@ private:
#endif
}
};
#endif // MKXPZ_RETRO
struct GraphicsPrivate {
/* Screen resolution, ie. the resolution at which
@ -800,7 +810,9 @@ struct GraphicsPrivate {
ScreenScene screen;
RGSSThreadData *threadData;
#ifndef MKXPZ_RETRO
SDL_GLContext glCtx;
#endif // MKXPZ_RETRO
int frameRate;
int frameCount;
@ -809,7 +821,9 @@ struct GraphicsPrivate {
double last_update;
#ifndef MKXPZ_RETRO
FPSLimiter fpsLimiter;
#endif // MKXPZ_RETRO
// Can be set from Ruby. Takes priority over config setting.
bool useFrameSkip;
@ -827,9 +841,11 @@ struct GraphicsPrivate {
std::vector<double> avgFPSData;
double last_avg_update;
#ifndef MKXPZ_RETRO
SDL_mutex *avgFPSLock;
SDL_mutex *glResourceLock;
#endif // MKXPZ_RETRO
bool multithreadedMode;
/* Global list of all live Disposables
@ -838,27 +854,58 @@ struct GraphicsPrivate {
GraphicsPrivate(RGSSThreadData *rtData)
: scResLores(DEF_SCREEN_W, DEF_SCREEN_H),
#ifdef MKXPZ_RETRO
scRes(DEF_SCREEN_W, DEF_SCREEN_H), // TODO: get from config
#else
scRes(rtData->config.enableHires ? (int)lround(rtData->config.framebufferScalingFactor * DEF_SCREEN_W) : DEF_SCREEN_W,
rtData->config.enableHires ? (int)lround(rtData->config.framebufferScalingFactor * DEF_SCREEN_H) : DEF_SCREEN_H),
#endif // MKXPZ_RETRO
scSize(scRes),
#ifdef MKXPZ_RETRO
winSize(640, 480), // TODO: use actual screen size
#else
winSize(rtData->config.defScreenW, rtData->config.defScreenH),
#endif // MKXPZ_RETRO
screen(scRes.x, scRes.y), threadData(rtData),
glCtx(SDL_GL_GetCurrentContext()), multithreadedMode(true),
#ifndef MKXPZ_RETRO
glCtx(SDL_GL_GetCurrentContext()),
#endif // MKXPZ_RETRO
multithreadedMode(true),
frameRate(DEF_FRAMERATE), frameCount(0), brightness(255),
fpsLimiter(frameRate), useFrameSkip(rtData->config.frameSkip), frozen(false),
#ifndef MKXPZ_RETRO
fpsLimiter(frameRate),
#endif // MKXPZ_RETRO
#ifdef MKXPZ_RETRO
useFrameSkip(false), // TODO: get from config
#else
useFrameSkip(rtData->config.frameSkip),
#endif // MKXPZ_RETRO
frozen(false),
last_update(0), last_avg_update(0), backingScaleFactor(1), integerScaleFactor(0, 0),
#ifdef MKXPZ_RETRO
integerScaleActive(false),
integerLastMileScaling(false)
#else
integerScaleActive(rtData->config.integerScaling.active),
integerLastMileScaling(rtData->config.integerScaling.lastMileScaling) {
integerLastMileScaling(rtData->config.integerScaling.lastMileScaling)
#endif // MKXPZ_RETRO
{
avgFPSData = std::vector<double>();
#ifndef MKXPZ_RETRO
avgFPSLock = SDL_CreateMutex();
glResourceLock = SDL_CreateMutex();
#endif // MKXPZ_RETRO
if (integerScaleActive) {
integerScaleFactor = Vec2i(0, 0);
rebuildIntegerScaleBuffer();
}
#ifdef MKXPZ_RETRO
recalculateScreenSize(true); // TODO: get from config
#else
recalculateScreenSize(rtData->config.fixedAspectRatio);
#endif // MKXPZ_RETRO
updateScreenResoRatio(rtData);
TEXFBO::init(frozenScene);
@ -868,22 +915,28 @@ struct GraphicsPrivate {
FloatRect screenRect(0, 0, scRes.x, scRes.y);
screenQuad.setTexPosRect(screenRect, screenRect);
#ifndef MKXPZ_RETRO
fpsLimiter.resetFrameAdjust();
#endif // MKXPZ_RETRO
}
~GraphicsPrivate() {
TEXFBO::fini(frozenScene);
TEXFBO::fini(integerScaleBuffer);
#ifndef MKXPZ_RETRO
SDL_DestroyMutex(avgFPSLock);
SDL_DestroyMutex(glResourceLock);
#endif // MKXPZ_RETRO
}
void updateScreenResoRatio(RGSSThreadData *rtData) {
#ifndef MKXPZ_RETRO
Vec2 &ratio = rtData->sizeResoRatio;
ratio.x = (float)scRes.x / scSize.x * backingScaleFactor;
ratio.y = (float)scRes.y / scSize.y * backingScaleFactor;
rtData->screenOffset = scOffset / backingScaleFactor;
#endif // MKXPZ_RETRO
}
/* Enforces fixed aspect ratio, if desired */
@ -966,6 +1019,7 @@ struct GraphicsPrivate {
}
void checkResize(bool skipIntScaleBuffer = false) {
#ifndef MKXPZ_RETRO
if (threadData->windowSizeMsg.poll(winSize)) {
/* Query the actual size in pixels, not units */
Vec2i drawableSize(winSize);
@ -987,6 +1041,7 @@ struct GraphicsPrivate {
SDL_Rect screen = {scOffset.x, scOffset.y, scSize.x, scSize.y};
threadData->ethread->notifyGameScreenChange(screen);
}
#endif // MKXPZ_RETRO
}
void checkShutDownReset() {
@ -1002,12 +1057,16 @@ struct GraphicsPrivate {
}
void swapGLBuffer() {
#ifndef MKXPZ_RETRO
fpsLimiter.delay();
SDL_GL_SwapWindow(threadData->window);
#endif // MKXPZ_RETRO
++frameCount;
#ifndef MKXPZ_RETRO
threadData->ethread->notifyFrame();
#endif // MKXPZ_RETRO
}
void compositeToBuffer(TEXFBO &buffer) {
@ -1113,6 +1172,7 @@ struct GraphicsPrivate {
}
void checkSyncLock() {
#ifndef MKXPZ_RETRO
if (!threadData->syncPoint.mainSyncLocked())
return;
@ -1124,46 +1184,60 @@ struct GraphicsPrivate {
SDL_GL_MakeCurrent(threadData->window, glCtx);
fpsLimiter.resetFrameAdjust();
#endif // MKXPZ_RETRO
}
double averageFPS() {
double ret = 0;
#ifndef MKXPZ_RETRO
SDL_LockMutex(avgFPSLock);
#endif // MKXPZ_RETRO
for (double times : avgFPSData)
ret += times;
ret = 1 / (ret / avgFPSData.size());
#ifndef MKXPZ_RETRO
SDL_UnlockMutex(avgFPSLock);
#endif // MKXPZ_RETRO
return ret;
}
void setLock(bool force = false) {
if (!(force || multithreadedMode)) return;
#ifndef MKXPZ_RETRO
SDL_LockMutex(glResourceLock);
SDL_GL_MakeCurrent(threadData->window, threadData->glContext);
#endif // MKXPZ_RETRO
}
void releaseLock(bool force = false) {
if (!(force || multithreadedMode)) return;
#ifndef MKXPZ_RETRO
SDL_UnlockMutex(glResourceLock);
#endif // MKXPZ_RETRO
}
void updateAvgFPS() {
#ifndef MKXPZ_RETRO
SDL_LockMutex(avgFPSLock);
#endif // MKXPZ_RETRO
if (avgFPSData.size() > 40)
avgFPSData.erase(avgFPSData.begin());
double time = shState->runTime();
avgFPSData.push_back(time - last_avg_update);
last_avg_update = time;
#ifndef MKXPZ_RETRO
SDL_UnlockMutex(avgFPSLock);
#endif // MKXPZ_RETRO
}
};
Graphics::Graphics(RGSSThreadData *data) {
p = new GraphicsPrivate(data);
#ifndef MKXPZ_RETRO
if (data->config.syncToRefreshrate) {
p->frameRate = data->refreshRate;
p->fpsLimiter.disabled = true;
@ -1172,6 +1246,7 @@ Graphics::Graphics(RGSSThreadData *data) {
} else if (data->config.fixedFramerate < 0) {
p->fpsLimiter.disabled = true;
}
#endif // MKXPZ_RETRO
}
Graphics::~Graphics() { delete p; }
@ -1185,6 +1260,7 @@ double Graphics::lastUpdate() {
}
void Graphics::update(bool checkForShutdown) {
#ifndef MKXPZ_RETRO
p->threadData->rqWindowAdjust.wait();
p->last_update = shState->runTime();
@ -1226,6 +1302,7 @@ void Graphics::update(bool checkForShutdown) {
}
p->checkResize();
#endif // MKXPZ_RETRO
p->redrawScreen();
}
@ -1292,6 +1369,7 @@ void Graphics::transition(int duration, const char *filename, int vague) {
glState.blend.pushSet(false);
for (int i = 0; i < duration; ++i) {
#ifndef MKXPZ_RETRO
/* We need to clean up transMap properly before
* a possible longjmp, so we manually test for
* shutdown/reset here */
@ -1308,6 +1386,7 @@ void Graphics::transition(int duration, const char *filename, int vague) {
scriptBinding->reset();
return;
}
#endif // MKXPZ_RETRO
p->checkSyncLock();
@ -1352,7 +1431,11 @@ void Graphics::transition(int duration, const char *filename, int vague) {
p->frozen = false;
}
void Graphics::frameReset() {p->fpsLimiter.resetFrameAdjust();}
void Graphics::frameReset() {
#ifndef MKXPZ_RETRO
p->fpsLimiter.resetFrameAdjust();
#endif // MKXPZ_RETRO
}
static void guardDisposed() {}
@ -1369,7 +1452,9 @@ void Graphics::setFrameRate(int value) {
if (p->threadData->config.fixedFramerate > 0)
return;
#ifndef MKXPZ_RETRO
p->fpsLimiter.setDesiredFPS(p->frameRate);
#endif // MKXPZ_RETRO
//shState->input().recalcRepeat((unsigned int)p->frameRate);
}
@ -1441,6 +1526,7 @@ void Graphics::fadein(int duration) {
Bitmap *Graphics::snapToBitmap() {
p->screen.composite();
#ifndef MKXPZ_RETRO
if (shState->config().enableHires) {
// TODO: Maybe don't reconstruct this struct every time?
TEXFBO tf;
@ -1450,6 +1536,7 @@ Bitmap *Graphics::snapToBitmap() {
return new Bitmap(tf);
}
#endif // MKXPZ_RETRO
return new Bitmap(p->screen.getPP().frontBuffer());
}
@ -1475,28 +1562,40 @@ int Graphics::displayContentHeight() const {
}
int Graphics::displayWidth() const {
#ifdef MKXPZ_RETRO
return 640; // TODO: use actual width
#else
SDL_DisplayMode dm{};
SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(shState->sdlWindow()), &dm);
return dm.w / p->backingScaleFactor;
#endif // MKXPZ_RETRO
}
int Graphics::displayHeight() const {
#ifdef MKXPZ_RETRO
return 480; // TODO: use actual height
#else
SDL_DisplayMode dm{};
SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(shState->sdlWindow()), &dm);
return dm.h / p->backingScaleFactor;
#endif // MKXPZ_RETRO
}
void Graphics::resizeScreen(int width, int height) {
#ifndef MKXPZ_RETRO
p->threadData->rqWindowAdjust.wait();
#endif // MKXPZ_RETRO
p->checkResize(true);
Vec2i sizeLores(width, height);
#ifndef MKXPZ_RETRO
if (shState->config().enableHires) {
double framebufferScalingFactor = shState->config().framebufferScalingFactor;
width = (int)lround(framebufferScalingFactor * width);
height = (int)lround(framebufferScalingFactor * height);
}
#endif // MKXPZ_RETRO
Vec2i size(width, height);
@ -1518,28 +1617,39 @@ void Graphics::resizeScreen(int width, int height) {
glState.scissorBox.set(IntRect(0, 0, p->scRes.x, p->scRes.y));
#ifndef MKXPZ_RETRO
shState->eThread().requestWindowResize(width, height);
#endif // MKXPZ_RETRO
}
void Graphics::resizeWindow(int width, int height, bool center) {
#ifndef MKXPZ_RETRO
p->threadData->rqWindowAdjust.wait();
#endif // MKXPZ_RETRO
p->checkResize();
if (width == p->winSize.x / p->backingScaleFactor &&
height == p->winSize.y / p->backingScaleFactor)
return;
#ifndef MKXPZ_RETRO
shState->eThread().requestWindowResize(width, height);
#endif // MKXPZ_RETRO
if (center)
this->center();
}
bool Graphics::updateMovieInput(Movie *movie) {
#ifdef MKXPZ_RETRO
return false; // TODO
#else
return p->threadData->rqTerm || p->threadData->rqReset;
#endif // MKXPZ_RETRO
}
void Graphics::playMovie(const char *filename, int volume_, bool skippable) {
#ifndef MKXPZ_RETRO
if (shState->config().enableHires) {
Debug() << "BUG: High-res Graphics playMovie not implemented";
}
@ -1572,10 +1682,13 @@ void Graphics::playMovie(const char *filename, int volume_, bool skippable) {
}
delete movie;
#endif // MKXPZ_RETRO
}
void Graphics::screenshot(const char *filename) {
#ifndef MKXPZ_RETRO
p->threadData->rqWindowAdjust.wait();
#endif // MKXPZ_RETRO
Bitmap *ss = snapToBitmap();
ss->saveToFile(filename);
ss->dispose();
@ -1606,55 +1719,81 @@ void Graphics::reset() {
p->dispList.clear();
/* Reset attributes (frame count not included) */
#ifndef MKXPZ_RETRO
p->fpsLimiter.resetFrameAdjust();
#endif // MKXPZ_RETRO
p->frozen = false;
p->screen.getPP().clearBuffers();
setFrameRate(DEF_FRAMERATE);
setBrightness(255);
#ifndef MKXPZ_RETRO
// Always update at least once to clear the screen
if (p->threadData->rqResetFinish)
#endif // MKXPZ_RETRO
update();
#ifndef MKXPZ_RETRO
else
repaintWait(p->threadData->rqResetFinish, false);
p->threadData->rqReset.clear();
#endif // MKXPZ_RETRO
}
void Graphics::center() {
#ifndef MKXPZ_RETRO
p->threadData->rqWindowAdjust.wait();
if (getFullscreen())
return;
p->threadData->ethread->requestWindowCenter();
#endif // MKXPZ_RETRO
}
bool Graphics::getFullscreen() const {
#ifdef MKXPZ_RETRO
return false; // TODO
#else
return p->threadData->ethread->getFullscreen();
#endif // MKXPZ_RETRO
}
void Graphics::setFullscreen(bool value) {
#ifndef MKXPZ_RETRO
p->threadData->ethread->requestFullscreenMode(value);
#endif // MKXPZ_RETRO
}
bool Graphics::getShowCursor() const {
#ifdef MKXPZ_RETRO
return true; // TODO
#else
return p->threadData->ethread->getShowCursor();
#endif // MKXPZ_RETRO
}
void Graphics::setShowCursor(bool value) {
#ifndef MKXPZ_RETRO
p->threadData->ethread->requestShowCursor(value);
#endif // MKXPZ_RETRO
}
bool Graphics::getFixedAspectRatio() const
{
// It's a bit hacky to expose config values as a Graphics
// attribute, but there's really no point in state duplication
#ifdef MKXPZ_RETRO
return true; // TODO: get from config
#else
return shState->config().fixedAspectRatio;
#endif // MKXPZ_RETRO
}
void Graphics::setFixedAspectRatio(bool value)
{
#ifndef MKXPZ_RETRO
shState->config().fixedAspectRatio = value;
#endif // MKXPZ_RETRO
p->recalculateScreenSize(p->threadData->config.fixedAspectRatio);
p->findHighestIntegerScale();
p->recalculateScreenSize(p->threadData->config.fixedAspectRatio);
@ -1664,12 +1803,18 @@ void Graphics::setFixedAspectRatio(bool value)
int Graphics::getSmoothScaling() const
{
// Same deal as with fixed aspect ratio
#ifdef MKXPZ_RETRO
return 0; // TODO: get from config
#else
return shState->config().smoothScaling;
#endif // MKXPZ_RETRO
}
void Graphics::setSmoothScaling(int value)
{
#ifndef MKXPZ_RETRO
shState->config().smoothScaling = value;
#endif // MKXPZ_RETRO
}
bool Graphics::getIntegerScaling() const
@ -1716,7 +1861,9 @@ double Graphics::getScale() const {
}
void Graphics::setScale(double factor) {
#ifndef MKXPZ_RETRO
p->threadData->rqWindowAdjust.wait();
#endif // MKXPZ_RETRO
factor = clamp(factor, 0.5, 4.0);
if (factor == getScale())
@ -1725,7 +1872,9 @@ void Graphics::setScale(double factor) {
int widthpx = p->scRes.x * factor;
int heightpx = p->scRes.y * factor;
#ifndef MKXPZ_RETRO
shState->eThread().requestWindowResize(widthpx, heightpx);
#endif // MKXPZ_RETRO
}
bool Graphics::getFrameskip() const { return p->useFrameSkip; }
@ -1754,10 +1903,12 @@ void Graphics::repaintWait(const AtomicFlag &exitCond, bool checkReset) {
FBO::clear();
p->metaBlitBufferFlippedScaled(scaleIsSpecial);
#ifndef MKXPZ_RETRO
SDL_GL_SwapWindow(p->threadData->window);
p->fpsLimiter.delay();
p->threadData->ethread->notifyFrame();
#endif // MKXPZ_RETRO
}
GLMeta::blitEnd();

View file

@ -82,8 +82,8 @@ struct SharedStatePrivate
#endif // MKXPZ_RETRO
SharedMidiState midiState;
#ifndef MKXPZ_RETRO
Graphics graphics;
#ifndef MKXPZ_RETRO
Input input;
Audio audio;
#endif // MKXPZ_RETRO
@ -127,8 +127,8 @@ struct SharedStatePrivate
#else
midiState(threadData->config),
#endif // MKXPZ_RETRO
#ifndef MKXPZ_RETRO
graphics(threadData),
#ifndef MKXPZ_RETRO
input(*threadData),
audio(*threadData),
#endif // MKXPZ_RETRO
@ -276,7 +276,9 @@ GSATT(FileSystem&, fileSystem)
GSATT(EventThread&, eThread)
GSATT(RGSSThreadData&, rtData)
GSATT(Config&, config)
#endif // MKXPZ_RETRO
GSATT(Graphics&, graphics)
#ifndef MKXPZ_RETRO
GSATT(Input&, input)
GSATT(Audio&, audio)
#endif // MKXPZ_RETRO
@ -435,11 +437,7 @@ SharedState::SharedState(RGSSThreadData *threadData)
try
{
p->init(threadData);
#ifdef MKXPZ_RETRO
p->screen = new Scene(); // TODO: implement
#else
p->screen = p->graphics.getScreen();
#endif // MKXPZ_RETRO
}
catch (const Exception &exc)
{

View file

@ -9,6 +9,37 @@
#include <iostream>
#include <unistd.h>
#ifdef MKXPZ_RETRO
struct AtomicFlag
{
AtomicFlag() : atom(false) {}
void set()
{
atom = true;
}
void clear()
{
atom = false;
}
void wait() {}
void reset()
{
set();
}
operator bool() const
{
return atom;
}
private:
mutable bool atom;
};
#else
struct AtomicFlag
{
AtomicFlag()
@ -45,6 +76,7 @@ struct AtomicFlag
private:
mutable SDL_atomic_t atom;
};
#endif // MKXPZ_RETRO
template<class C, void (C::*func)()>
int __sdlThreadFun(void *obj)