Fix wrong size generated of FBO for some games which uses it as render-to-texture

This commit is contained in:
raven02 2013-08-10 17:22:22 +08:00
parent e03acc4c58
commit c2a86d647f
3 changed files with 47 additions and 39 deletions

View File

@ -375,35 +375,40 @@ VirtualFramebuffer *FramebufferManager::GetDisplayFBO() {
return 0;
}
void GetViewportDimensions(int &w, int &h) {
float vpXa = getFloat24(gstate.viewportx1);
float vpYa = getFloat24(gstate.viewporty1);
w = (int)fabsf(vpXa * 2);
h = (int)fabsf(vpYa * 2);
}
// Heuristics to figure out the size of FBO to create.
void GuessDrawingSize(int &drawing_width, int &drawing_height) {
int viewport_width, viewport_height;
int default_width = 480;
int default_height = 272;
int regionX2 = (gstate.getRegionX2() + 1) ;
int regionY2 = (gstate.getRegionY2() + 1) ;
int fb_stride = gstate.fbwidth & 0x3C0;
GetViewportDimensions(viewport_width, viewport_height);
int viewport_width = (int) gstate.getViewportX1();
int viewport_height = (int) gstate.getViewportY1();
int region_width = (gstate.getRegionX2() + 1) ;
int region_height = (gstate.getRegionY2() + 1) ;
int fb_width = gstate.fbwidth & 0x3C0;
// Generated FBO shouldn't greate than 512x512
if ( viewport_width > 512 && viewport_height > 512 ) {
viewport_width = default_width;
viewport_height = default_height;
DEBUG_LOG(HLE,"Viewport : %ix%i, Region : %ix%i, Stride: %i", viewport_width,viewport_height, region_width, region_height, fb_width);
// Just in case viewport return as 0x0 like FF Type-0
if (viewport_width <= 1 && viewport_height <=1) {
drawing_width = default_width;
drawing_height = default_height;
}
if (fb_stride < 512) {
drawing_width = std::min(viewport_width, regionX2);
drawing_height = std::min(viewport_height, regionY2);
if (fb_width < 512) {
if (fb_width != viewport_width) {
drawing_width = viewport_width;
drawing_height = viewport_height;
} else {
drawing_width = region_width;
drawing_height = region_height;
}
} else {
drawing_width = std::max(viewport_width, default_width);
drawing_height = std::max(viewport_height, default_height);
if (fb_width != region_width) {
drawing_width = default_width;
drawing_height = default_height;
} else {
drawing_width = region_width;
drawing_height = region_height;
}
}
}

View File

@ -194,7 +194,8 @@ inline void TextureCache::AttachFramebuffer(TexCacheEntry *entry, u32 address, V
if (entry->format != framebuffer->format) {
WARN_LOG_REPORT_ONCE(diffFormat1, HLE, "Render to texture with different formats %d != %d", entry->format, framebuffer->format);
// If it already has one, let's hope that one is correct.
AttachFramebufferInvalid(entry, framebuffer);
// Try to not bind FB now as it seems to be attached some strange stuff on top of the original FB.
//AttachFramebufferInvalid(entry, framebuffer);
} else {
AttachFramebufferValid(entry, framebuffer);
}

View File

@ -20,6 +20,23 @@
#include "../Globals.h"
#include "ge_constants.h"
// PSP uses a curious 24-bit float - it's basically the top 24 bits of a regular IEEE754 32-bit float.
// This is used for light positions, transform matrices, you name it.
inline float getFloat24(unsigned int data)
{
data <<= 8;
float f;
memcpy(&f, &data, 4);
return f;
}
// in case we ever want to generate PSP display lists...
inline unsigned int toFloat24(float f) {
unsigned int i;
memcpy(&i, &f, 4);
return i >> 8;
}
struct GPUgstate
{
// Getting rid of this ugly union in favor of the accessor functions
@ -316,6 +333,8 @@ struct GPUgstate
int getRegionY1() const { return (region1 >> 10) & 0x3FF; }
int getRegionX2() const { return (region2 & 0x3FF); }
int getRegionY2() const { return ((region2 >> 10) & 0x3FF); }
float getViewportX1() const { return fabsf(getFloat24(viewportx1) * 2.0f); }
float getViewportY1() const { return fabsf(getFloat24(viewporty1) * 2.0f); }
// Vertex type
bool isModeThrough() const { return (vertType & GE_VTYPE_THROUGH) != 0; }
@ -431,23 +450,6 @@ void InitGfxState();
void ShutdownGfxState();
void ReapplyGfxState();
// PSP uses a curious 24-bit float - it's basically the top 24 bits of a regular IEEE754 32-bit float.
// This is used for light positions, transform matrices, you name it.
inline float getFloat24(unsigned int data)
{
data <<= 8;
float f;
memcpy(&f, &data, 4);
return f;
}
// in case we ever want to generate PSP display lists...
inline unsigned int toFloat24(float f) {
unsigned int i;
memcpy(&i, &f, 4);
return i >> 8;
}
class GPUInterface;
extern GPUgstate gstate;