mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-07-02 05:16:19 +12:00
SDL/Qt: Better resizing & fullscreen support
This commit is contained in:
parent
bfeee04d3e
commit
630952f36b
6 changed files with 85 additions and 7 deletions
|
@ -53,10 +53,12 @@ class Renderer {
|
||||||
|
|
||||||
// Should hw renderers hash textures? Stored separately from emulatorConfig because we'll be accessing it constantly, might be merged eventually
|
// Should hw renderers hash textures? Stored separately from emulatorConfig because we'll be accessing it constantly, might be merged eventually
|
||||||
bool hashTextures = false;
|
bool hashTextures = false;
|
||||||
|
bool outputSizeChanged = true;
|
||||||
|
|
||||||
EmulatorConfig* emulatorConfig = nullptr;
|
EmulatorConfig* emulatorConfig = nullptr;
|
||||||
|
|
||||||
void doSoftwareTextureCopy(u32 inputAddr, u32 outputAddr, u32 copySize, u32 inputWidth, u32 inputGap, u32 outputWidth, u32 outputGap);
|
void doSoftwareTextureCopy(u32 inputAddr, u32 outputAddr, u32 copySize, u32 inputWidth, u32 inputGap, u32 outputWidth, u32 outputGap);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs);
|
Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs);
|
||||||
virtual ~Renderer();
|
virtual ~Renderer();
|
||||||
|
@ -121,6 +123,7 @@ class Renderer {
|
||||||
void setDepthBufferLoc(u32 loc) { depthBufferLoc = loc; }
|
void setDepthBufferLoc(u32 loc) { depthBufferLoc = loc; }
|
||||||
|
|
||||||
void setOutputSize(u32 width, u32 height) {
|
void setOutputSize(u32 width, u32 height) {
|
||||||
|
outputSizeChanged = true;
|
||||||
outputWindowWidth = width;
|
outputWindowWidth = width;
|
||||||
outputWindowHeight = height;
|
outputWindowHeight = height;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ class RendererGL final : public Renderer {
|
||||||
OpenGL::VertexArray hwShaderVAO;
|
OpenGL::VertexArray hwShaderVAO;
|
||||||
OpenGL::VertexBuffer vbo;
|
OpenGL::VertexBuffer vbo;
|
||||||
|
|
||||||
// Data
|
// Data that will be uploaded to the ubershader
|
||||||
struct {
|
struct {
|
||||||
// TEV configuration uniform locations
|
// TEV configuration uniform locations
|
||||||
GLint textureEnvSourceLoc = -1;
|
GLint textureEnvSourceLoc = -1;
|
||||||
|
@ -146,6 +146,15 @@ class RendererGL final : public Renderer {
|
||||||
PICA::ShaderGen::FragmentGenerator fragShaderGen;
|
PICA::ShaderGen::FragmentGenerator fragShaderGen;
|
||||||
OpenGL::Driver driverInfo;
|
OpenGL::Driver driverInfo;
|
||||||
|
|
||||||
|
// Information about the final 3DS screen -> Window blit, accounting for things like scaling and shifting the output based on
|
||||||
|
// the window's dimensions.
|
||||||
|
struct {
|
||||||
|
int destX = 0;
|
||||||
|
int destY = 0;
|
||||||
|
int destWidth = 400;
|
||||||
|
int destHeight = 480;
|
||||||
|
} blitInfo;
|
||||||
|
|
||||||
MAKE_LOG_FUNCTION(log, rendererLogger)
|
MAKE_LOG_FUNCTION(log, rendererLogger)
|
||||||
void setupBlending();
|
void setupBlending();
|
||||||
void setupStencilTest(bool stencilEnable);
|
void setupStencilTest(bool stencilEnable);
|
||||||
|
|
|
@ -88,6 +88,16 @@ class RendererMTL final : public Renderer {
|
||||||
MTL::Texture* lastColorTexture = nullptr;
|
MTL::Texture* lastColorTexture = nullptr;
|
||||||
MTL::Texture* lastDepthTexture = nullptr;
|
MTL::Texture* lastDepthTexture = nullptr;
|
||||||
|
|
||||||
|
// Information about the final 3DS screen -> Window blit, accounting for things like scaling and shifting the output based on
|
||||||
|
// the window's dimensions.
|
||||||
|
struct {
|
||||||
|
float topScreenX = 0;
|
||||||
|
float topScreenY = 0;
|
||||||
|
float bottomScreenX = 40;
|
||||||
|
float bottomScreenY = 240;
|
||||||
|
float scale = 1.0;
|
||||||
|
} blitInfo;
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
std::string nextRenderPassName;
|
std::string nextRenderPassName;
|
||||||
|
|
||||||
|
|
|
@ -582,7 +582,33 @@ void RendererGL::display() {
|
||||||
if constexpr (!Helpers::isHydraCore()) {
|
if constexpr (!Helpers::isHydraCore()) {
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
screenFramebuffer.bind(OpenGL::ReadFramebuffer);
|
screenFramebuffer.bind(OpenGL::ReadFramebuffer);
|
||||||
glBlitFramebuffer(0, 0, 400, 480, 0, 0, outputWindowWidth, outputWindowHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
||||||
|
if (outputSizeChanged) {
|
||||||
|
outputSizeChanged = false;
|
||||||
|
|
||||||
|
const float srcAspect = 400.0f / 480.0f; // 3DS aspect ratio
|
||||||
|
const float dstAspect = float(outputWindowWidth) / float(outputWindowHeight);
|
||||||
|
|
||||||
|
blitInfo.destWidth = outputWindowWidth;
|
||||||
|
blitInfo.destHeight = outputWindowHeight;
|
||||||
|
blitInfo.destX = 0;
|
||||||
|
blitInfo.destY = 0;
|
||||||
|
|
||||||
|
if (dstAspect > srcAspect) {
|
||||||
|
// Window is wider than source
|
||||||
|
blitInfo.destWidth = int(outputWindowHeight * srcAspect + 0.5f);
|
||||||
|
blitInfo.destX = (outputWindowWidth - blitInfo.destWidth) / 2;
|
||||||
|
} else {
|
||||||
|
// Window is taller than source
|
||||||
|
blitInfo.destHeight = int(outputWindowWidth / srcAspect + 0.5f);
|
||||||
|
blitInfo.destY = (outputWindowHeight - blitInfo.destHeight) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glBlitFramebuffer(
|
||||||
|
0, 0, 400, 480, blitInfo.destX, blitInfo.destY, blitInfo.destX + blitInfo.destWidth, blitInfo.destY + blitInfo.destHeight,
|
||||||
|
GL_COLOR_BUFFER_BIT, GL_LINEAR
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,16 +103,44 @@ void RendererMTL::display() {
|
||||||
renderCommandEncoder->setRenderPipelineState(displayPipeline);
|
renderCommandEncoder->setRenderPipelineState(displayPipeline);
|
||||||
renderCommandEncoder->setFragmentSamplerState(nearestSampler, 0);
|
renderCommandEncoder->setFragmentSamplerState(nearestSampler, 0);
|
||||||
|
|
||||||
|
if (outputSizeChanged) {
|
||||||
|
outputSizeChanged = false;
|
||||||
|
|
||||||
|
const float srcAspect = 400.0 / 480.0;
|
||||||
|
const float destAspect = float(outputWindowWidth) / float(outputWindowHeight);
|
||||||
|
int destX = 0, destY = 0, destWidth = outputWindowWidth, destHeight = outputWindowHeight;
|
||||||
|
|
||||||
|
if (destAspect > srcAspect) {
|
||||||
|
// Window is wider than source
|
||||||
|
destWidth = int(outputWindowHeight * srcAspect + 0.5f);
|
||||||
|
destX = (outputWindowWidth - destWidth) / 2;
|
||||||
|
} else {
|
||||||
|
// Window is taller than source
|
||||||
|
destHeight = int(outputWindowWidth / srcAspect + 0.5f);
|
||||||
|
destY = (outputWindowHeight - destHeight) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
blitInfo.scale = float(destWidth) / 400.0f;
|
||||||
|
blitInfo.topScreenX = float(destX);
|
||||||
|
blitInfo.topScreenY = float(destY + (destHeight - int(480 * blitInfo.scale)) / 2);
|
||||||
|
blitInfo.bottomScreenX = float(destX) + 40 * blitInfo.scale;
|
||||||
|
blitInfo.bottomScreenY = blitInfo.topScreenY + 240 * blitInfo.scale;
|
||||||
|
}
|
||||||
|
|
||||||
// Top screen
|
// Top screen
|
||||||
if (topScreen) {
|
if (topScreen) {
|
||||||
renderCommandEncoder->setViewport(MTL::Viewport{0, 0, 400, 240, 0.0f, 1.0f});
|
renderCommandEncoder->setViewport(
|
||||||
|
MTL::Viewport{blitInfo.topScreenX, blitInfo.topScreenY + 240 * blitInfo.scale, 400 * blitInfo.scale, 240 * blitInfo.scale, 0.0f, 1.0f}
|
||||||
|
);
|
||||||
renderCommandEncoder->setFragmentTexture(topScreen->get().texture, 0);
|
renderCommandEncoder->setFragmentTexture(topScreen->get().texture, 0);
|
||||||
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangleStrip, NS::UInteger(0), NS::UInteger(4));
|
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangleStrip, NS::UInteger(0), NS::UInteger(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bottom screen
|
// Bottom screen
|
||||||
if (bottomScreen) {
|
if (bottomScreen) {
|
||||||
renderCommandEncoder->setViewport(MTL::Viewport{40, 240, 320, 240, 0.0f, 1.0f});
|
renderCommandEncoder->setViewport(
|
||||||
|
MTL::Viewport{blitInfo.bottomScreenX, blitInfo.bottomScreenY, 320 * blitInfo.scale, 240 * blitInfo.scale, 0.0f, 1.0f}
|
||||||
|
);
|
||||||
renderCommandEncoder->setFragmentTexture(bottomScreen->get().texture, 0);
|
renderCommandEncoder->setFragmentTexture(bottomScreen->get().texture, 0);
|
||||||
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangleStrip, NS::UInteger(0), NS::UInteger(4));
|
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangleStrip, NS::UInteger(0), NS::UInteger(4));
|
||||||
}
|
}
|
||||||
|
|
|
@ -415,9 +415,8 @@ void MainWindow::dispatchMessage(const EmulatorMessage& message) {
|
||||||
case MessageType::SetScreenSize: {
|
case MessageType::SetScreenSize: {
|
||||||
const u32 width = message.screenSize.width;
|
const u32 width = message.screenSize.width;
|
||||||
const u32 height = message.screenSize.height;
|
const u32 height = message.screenSize.height;
|
||||||
|
|
||||||
emu->setOutputSize(width, height);
|
|
||||||
screen->resizeSurface(width, height);
|
screen->resizeSurface(width, height);
|
||||||
|
emu->setOutputSize(width, height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,7 +565,10 @@ void MainWindow::handleScreenResize(u32 width, u32 height) {
|
||||||
message.screenSize.width = width;
|
message.screenSize.width = width;
|
||||||
message.screenSize.height = height;
|
message.screenSize.height = height;
|
||||||
|
|
||||||
sendMessage(message);
|
if (messageQueueMutex.try_lock()) {
|
||||||
|
messageQueue.push_back(message);
|
||||||
|
messageQueueMutex.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::initControllers() {
|
void MainWindow::initControllers() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue