Videosoftware realxfb: Fixed a few bugs while testing Zelda: Collectors Edition

* Don't force a frame to be progressive if it's already progressive.
 * Don't assume the framebuffer will be 640 pixels wide
 * Remember to offset the Luma channel by 16.
This commit is contained in:
Scott Mansell 2013-11-23 18:38:15 +13:00
parent 2abcc32bbd
commit a94940edd3
4 changed files with 19 additions and 17 deletions

View File

@ -511,7 +511,7 @@ namespace EfbInterface
} }
// Scanline buffer, leave room for borders // Scanline buffer, leave room for borders
yuv444 scanline[640+2]; yuv444 scanline[fbWidth+2];
// our internal yuv444 type is not normalized, so black is {0, 0, 0} instead of {16, 128, 128} // our internal yuv444 type is not normalized, so black is {0, 0, 0} instead of {16, 128, 128}
yuv444 black; yuv444 black;
@ -535,17 +535,17 @@ namespace EfbInterface
for (int i = 1, x = left; x < right; i+=2, x+=2) for (int i = 1, x = left; x < right; i+=2, x+=2)
{ {
// YU pixel // YU pixel
xfb_in_ram[x].Y = scanline[i].Y; xfb_in_ram[x].Y = scanline[i].Y + 16;
// we mix our color difrences in 10 bit space so it will round more accurately // we mix our color difrences in 10 bit space so it will round more accurately
// U[i] = 1/4 * U[i-1] + 1/2 * U[i] + 1/4 * U[i+1] // U[i] = 1/4 * U[i-1] + 1/2 * U[i] + 1/4 * U[i+1]
xfb_in_ram[x].UV = 128 + ((scanline[i-1].U + (scanline[i].U << 1) + scanline[i+1].U) >> 2); xfb_in_ram[x].UV = 128 + ((scanline[i-1].U + (scanline[i].U << 1) + scanline[i+1].U) >> 2);
// YV pixel // YV pixel
xfb_in_ram[x+1].Y = scanline[i+1].Y; xfb_in_ram[x+1].Y = scanline[i+1].Y + 16;
// V[i] = 1/4 * V[i-1] + 1/2 * V[i] + 1/4 * V[i+1] // V[i] = 1/4 * V[i-1] + 1/2 * V[i] + 1/4 * V[i+1]
xfb_in_ram[x+1].UV = 128 + ((scanline[i].V + (scanline[i+1].V << 1) + scanline[i+2].V) >> 2); xfb_in_ram[x+1].UV = 128 + ((scanline[i].V + (scanline[i+1].V << 1) + scanline[i+2].V) >> 2);
} }
xfb_in_ram += 640; xfb_in_ram += fbWidth;
} }
} }

View File

@ -172,14 +172,14 @@ void DrawButton(GLuint tex, float *coords)
} }
#endif #endif
void SWRenderer::UpdateColorTexture(EfbInterface::yuv422_packed *xfb) void SWRenderer::UpdateColorTexture(EfbInterface::yuv422_packed *xfb, u32 fbWidth, u32 fbHeight)
{ {
u32 offset = 0; u32 offset = 0;
u8 *TexturePointer = s_xfbColorTexture[!s_currentColorTexture]; u8 *TexturePointer = s_xfbColorTexture[!s_currentColorTexture];
for (u16 y = 0; y < EFB_HEIGHT; y++) for (u16 y = 0; y < fbHeight; y++)
{ {
for (u16 x = 0; x < EFB_WIDTH; x+=2) for (u16 x = 0; x < fbWidth; x+=2)
{ {
// We do this one color sample (aka 2 RGB pixles) at a time // We do this one color sample (aka 2 RGB pixles) at a time
int Y1 = xfb[x].Y - 16; int Y1 = xfb[x].Y - 16;
@ -199,7 +199,7 @@ void SWRenderer::UpdateColorTexture(EfbInterface::yuv422_packed *xfb)
TexturePointer[offset++] = min(255.0f, max(0.0f, 1.164f * Y2 + 2.017f * U )); TexturePointer[offset++] = min(255.0f, max(0.0f, 1.164f * Y2 + 2.017f * U ));
TexturePointer[offset++] = 255; TexturePointer[offset++] = 255;
} }
xfb += EFB_WIDTH; xfb += fbWidth;
} }
s_currentColorTexture = !s_currentColorTexture; s_currentColorTexture = !s_currentColorTexture;
} }

View File

@ -17,7 +17,7 @@ namespace SWRenderer
void RenderText(const char* pstr, int left, int top, u32 color); void RenderText(const char* pstr, int left, int top, u32 color);
void DrawDebugText(); void DrawDebugText();
void UpdateColorTexture(EfbInterface::yuv422_packed *xfb); void UpdateColorTexture(EfbInterface::yuv422_packed *xfb, u32 fbWidth, u32 fbHeight);
void DrawTexture(u8 *texture, int width, int height); void DrawTexture(u8 *texture, int width, int height);
void Swap(u32 fbWidth, u32 fbHeight); void Swap(u32 fbWidth, u32 fbHeight);

View File

@ -225,19 +225,21 @@ void VideoSoftware::Video_EndField()
return; return;
} }
if (!g_SWVideoConfig.bHwRasterizer) { if (!g_SWVideoConfig.bHwRasterizer) {
u32 xfbAddr = s_beginFieldArgs.xfbAddr;
if (s_beginFieldArgs.field != FIELD_PROGRESSIVE) {
// Force Progressive
xfbAddr = VideoInterface::GetXFBAddressTop();
// Force Progressive // All drivers make an assumption that the two fields are interleaved in the framebuffer
u32 xfbAddr = VideoInterface::GetXFBAddressTop(); // Give a warning if this isn't true.
if (xfbAddr + 1280 != VideoInterface::GetXFBAddressBottom()) {
// All drivers make an assumption that the two fields are interleaved in the framebuffer WARN_LOG(VIDEO, "Feilds are not interleaved in XFB as expected.");
// Give a warning if this isn't true. }
if (xfbAddr + 1280 != VideoInterface::GetXFBAddressBottom()) {
WARN_LOG(VIDEO, "Feilds are not interleaved in XFB as expected.");
} }
EfbInterface::yuv422_packed *xfb = (EfbInterface::yuv422_packed *) Memory::GetPointer(xfbAddr); EfbInterface::yuv422_packed *xfb = (EfbInterface::yuv422_packed *) Memory::GetPointer(xfbAddr);
SWRenderer::UpdateColorTexture(xfb); SWRenderer::UpdateColorTexture(xfb, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight);
} }
// Idealy we would just move all the opengl contex stuff to the CPU thread, but this gets // Idealy we would just move all the opengl contex stuff to the CPU thread, but this gets