From 1f76adb7a3f03f01bf038dc22f84a54fcd613f79 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 12 Apr 2014 20:46:38 -0700 Subject: [PATCH 1/3] If a larger framebuffer is needed, upgrade it once. This should prevent issues where it gets larger and smaller like in the past. --- GPU/GLES/Framebuffer.cpp | 17 +++++++++++++++-- GPU/GLES/Framebuffer.h | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 463d3a9669..90265e0807 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -708,6 +708,7 @@ void FramebufferManager::DoSetRenderFrameBuffer() { int buffer_width = drawing_width; int buffer_height = drawing_height; + bool embiggened = false; // Find a matching framebuffer VirtualFramebuffer *vfb = 0; @@ -718,8 +719,19 @@ void FramebufferManager::DoSetRenderFrameBuffer() { // Update fb stride in case it changed vfb->fb_stride = fb_stride; if (v->width < drawing_width && v->height < drawing_height) { - v->width = drawing_width; - v->height = drawing_height; + // Embiggen if it gets bigger, but only once. + // This prevents it happening over and over again. + if (!v->embiggened) { + // TODO: Could copy over the data. + embiggened = true; + vfb = NULL; + DestroyFramebuf(v); + vfbs_.erase(vfbs_.begin() + i); + break; + } else { + v->width = drawing_width; + v->height = drawing_height; + } } if (v->format != fmt) { v->width = drawing_width; @@ -755,6 +767,7 @@ void FramebufferManager::DoSetRenderFrameBuffer() { vfb->reallyDirtyAfterDisplay = true; vfb->memoryUpdated = false; vfb->depthUpdated = false; + vfb->embiggened = embiggened; if (g_Config.bTrueColor) { vfb->colorDepth = FBO_8888; diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 2aa9157b9f..ab0a3fa7c9 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -85,6 +85,7 @@ struct VirtualFramebuffer { bool dirtyAfterDisplay; bool reallyDirtyAfterDisplay; // takes frame skipping into account + bool embiggened; }; void CenterRect(float *x, float *y, float *w, float *h, From 1a53be45cced7f6b2c448e5fd965e541aafb1c81 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 12 Apr 2014 21:11:47 -0700 Subject: [PATCH 2/3] When uploading video pixels, detect w/h by size. Sometimes the framebuffer size is incorrect, but kinda works... but this is a problem for the video. Using the size gets us better. In Wild Arms XF, the framebuffer is 512x512, but that's not right. It's clear it should be 480x272. --- GPU/GLES/Framebuffer.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 90265e0807..8db616df11 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -1677,10 +1677,20 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size, bool safe) { // However, it doesn't seem to work for Star Ocean, at least if (useBufferedRendering_ && vfb->fbo) { DisableState(); - glstate.viewport.set(0, 0, vfb->renderWidth, vfb->renderHeight); fbo_bind_as_render_target(vfb->fbo); - if (gl_extensions.gpuVendor != GPU_VENDOR_POWERVR) - glstate.viewport.restore(); + + int w = vfb->bufferWidth; + int h = vfb->bufferHeight; + // Often, the framebuffer size is incorrect. But here we have the size. Bit of a hack. + if (vfb->fb_stride == 512 && (size == 512 * 272 * 4 || size == 512 * 272 * 2)) { + // Looks like a standard 480x272 sized framebuffer/video/etc. + w = 480; + h = 272; + } + // Scale by the render resolution factor. + w = (w * vfb->renderWidth) / vfb->bufferWidth; + h = (h * vfb->renderHeight) / vfb->bufferHeight; + glstate.viewport.set(0, vfb->renderHeight - h, w, h); needUnbind = true; DrawPixels(Memory::GetPointer(addr | 0x04000000), vfb->format, vfb->fb_stride); } else { From f462721394bb3174f462baa114bba1f406a3cfbf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 12 Apr 2014 23:08:04 -0700 Subject: [PATCH 3/3] Rather than only enlarging, watch for persistence. If the game keeps using something at a new size, we know it's time to make some adjustments. --- GPU/GLES/Framebuffer.cpp | 37 +++++++++++++++++++++---------------- GPU/GLES/Framebuffer.h | 5 ++++- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 8db616df11..7463bdd654 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -708,30 +708,19 @@ void FramebufferManager::DoSetRenderFrameBuffer() { int buffer_width = drawing_width; int buffer_height = drawing_height; - bool embiggened = false; // Find a matching framebuffer VirtualFramebuffer *vfb = 0; - for (size_t i = 0; i < vfbs_.size(); ++i) { + size_t i; + for (i = 0; i < vfbs_.size(); ++i) { VirtualFramebuffer *v = vfbs_[i]; if (MaskedEqual(v->fb_address, fb_address)) { vfb = v; // Update fb stride in case it changed vfb->fb_stride = fb_stride; if (v->width < drawing_width && v->height < drawing_height) { - // Embiggen if it gets bigger, but only once. - // This prevents it happening over and over again. - if (!v->embiggened) { - // TODO: Could copy over the data. - embiggened = true; - vfb = NULL; - DestroyFramebuf(v); - vfbs_.erase(vfbs_.begin() + i); - break; - } else { - v->width = drawing_width; - v->height = drawing_height; - } + v->width = drawing_width; + v->height = drawing_height; } if (v->format != fmt) { v->width = drawing_width; @@ -742,6 +731,20 @@ void FramebufferManager::DoSetRenderFrameBuffer() { } } + if (vfb && (drawing_width != vfb->bufferWidth || drawing_height != vfb->bufferHeight)) { + // If it's newly wrong, or changing every frame, just keep track. + if (vfb->newWidth != drawing_width || vfb->newHeight != drawing_height) { + vfb->newWidth = drawing_width; + vfb->newHeight = drawing_height; + vfb->lastFrameNewSize = gpuStats.numFlips; + } else if (vfb->lastFrameNewSize + FBO_OLD_AGE <= gpuStats.numFlips) { + // Okay, it's changed for a while (and stayed that way.) Let's start over. + DestroyFramebuf(vfb); + vfbs_.erase(vfbs_.begin() + i); + vfb = NULL; + } + } + float renderWidthFactor = (float)PSP_CoreParameter().renderWidth / 480.0f; float renderHeightFactor = (float)PSP_CoreParameter().renderHeight / 272.0f; @@ -756,6 +759,9 @@ void FramebufferManager::DoSetRenderFrameBuffer() { vfb->z_stride = z_stride; vfb->width = drawing_width; vfb->height = drawing_height; + vfb->newWidth = drawing_width; + vfb->newHeight = drawing_height; + vfb->lastFrameNewSize = gpuStats.numFlips; vfb->renderWidth = (u16)(drawing_width * renderWidthFactor); vfb->renderHeight = (u16)(drawing_height * renderHeightFactor); vfb->bufferWidth = buffer_width; @@ -767,7 +773,6 @@ void FramebufferManager::DoSetRenderFrameBuffer() { vfb->reallyDirtyAfterDisplay = true; vfb->memoryUpdated = false; vfb->depthUpdated = false; - vfb->embiggened = embiggened; if (g_Config.bTrueColor) { vfb->colorDepth = FBO_8888; diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index ab0a3fa7c9..4d96c7f4a8 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -79,13 +79,16 @@ struct VirtualFramebuffer { u16 usageFlags; + u16 newWidth; + u16 newHeight; + int lastFrameNewSize; + GEBufferFormat format; // virtual, right now they are all RGBA8888 FBOColorDepth colorDepth; FBO *fbo; bool dirtyAfterDisplay; bool reallyDirtyAfterDisplay; // takes frame skipping into account - bool embiggened; }; void CenterRect(float *x, float *y, float *w, float *h,