Fix pixel center and letter box issues

This commit is contained in:
Magnus Norddahl 2016-10-12 07:34:07 +02:00
parent 3c7d6234cb
commit 698b05ee69
3 changed files with 105 additions and 137 deletions

View file

@ -153,8 +153,8 @@ OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height,
VSync = vid_vsync;
BlendingRect.left = 0;
BlendingRect.top = 0;
BlendingRect.right = FBWidth;
BlendingRect.bottom = FBHeight;
BlendingRect.right = Width;
BlendingRect.bottom = Height;
In2D = 0;
Palettes = nullptr;
Textures = nullptr;
@ -186,21 +186,6 @@ OpenGLSWFrameBuffer::OpenGLSWFrameBuffer(void *hMonitor, int width, int height,
//Windowed = !(static_cast<Win32Video *>(Video)->GoFullscreen(fullscreen));
TrueHeight = height;
/*if (fullscreen)
{
for (Win32Video::ModeInfo *mode = static_cast<Win32Video *>(Video)->m_Modes; mode != nullptr; mode = mode->next)
{
if (mode->width == Width && mode->height == Height)
{
TrueHeight = mode->realheight;
PixelDoubling = mode->doubling;
break;
}
}
}*/
// Offset from top of screen to top of letterboxed screen
LBOffsetI = (TrueHeight - Height) / 2;
LBOffset = float(LBOffsetI);
CreateResources();
SetInitialState();
@ -650,28 +635,39 @@ void OpenGLSWFrameBuffer::DrawTriangleList(int minIndex, int numVertices, int st
void OpenGLSWFrameBuffer::Present()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
int clientWidth = GetClientWidth();
int clientHeight = GetClientHeight();
if (clientWidth > 0 && clientHeight > 0)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, clientWidth, clientHeight);
FBVERTEX verts[4];
float scale = MIN(clientWidth / (float)Width, clientHeight / (float)Height);
int letterboxWidth = (int)round(Width * scale);
int letterboxHeight = (int)round(Height * scale);
int letterboxX = (clientWidth - letterboxWidth) / 2;
int letterboxY = (clientHeight - letterboxHeight) / 2;
CalcFullscreenCoords(verts, false, true, 0, 0xFFFFFFFF);
//for (int i = 0; i < 4; i++)
// verts[i].tv = 1.0f - verts[i].tv;
SetTexture(0, OutputFB->Texture);
SetPixelShader(Shaders[SHADER_GammaCorrection]);
SetAlphaBlend(0);
EnableAlphaTest(false);
DrawTriangleFans(2, verts);
DrawLetterbox(letterboxX, letterboxY, letterboxWidth, letterboxHeight);
glViewport(letterboxX, letterboxY, letterboxWidth, letterboxHeight);
FBVERTEX verts[4];
CalcFullscreenCoords(verts, false, 0, 0xFFFFFFFF);
SetTexture(0, OutputFB->Texture);
SetPixelShader(Shaders[SHADER_GammaCorrection]);
SetAlphaBlend(0);
EnableAlphaTest(false);
DrawTriangleFans(2, verts);
}
SwapBuffers();
Debug->Update();
glViewport(0, 0, GetClientWidth(), GetClientHeight());
float screensize[4] = { (float)GetClientWidth(), (float)GetClientHeight(), 1.0f, 1.0f };
float screensize[4] = { (float)Width, (float)Height, 1.0f, 1.0f };
SetPixelShaderConstantF(PSCONST_ScreenSize, screensize, 1);
glBindFramebuffer(GL_FRAMEBUFFER, OutputFB->Framebuffer);
glViewport(0, 0, Width, Height);
}
//==========================================================================
@ -707,7 +703,7 @@ void OpenGLSWFrameBuffer::SetInitialState()
float weights[4] = { 77 / 256.f, 143 / 256.f, 37 / 256.f, 1 };
SetPixelShaderConstantF(PSCONST_Weights, weights, 1);
float screensize[4] = { (float)GetClientWidth(), (float)GetClientHeight(), 1.0f, 1.0f };
float screensize[4] = { (float)Width, (float)Height, 1.0f, 1.0f };
SetPixelShaderConstantF(PSCONST_ScreenSize, screensize, 1);
AlphaTestEnabled = false;
@ -846,14 +842,14 @@ bool OpenGLSWFrameBuffer::Reset()
{
ReleaseDefaultPoolItems();
if (!CreateFrameBuffer("OutputFB", Width, Height, &OutputFB))
return false;
glBindFramebuffer(GL_FRAMEBUFFER, OutputFB->Framebuffer);
if (!CreateFBTexture() || !CreateVertexes())
if (!CreateFrameBuffer("OutputFB", Width, Height, &OutputFB) || !CreateFBTexture() || !CreateVertexes())
{
return false;
}
glBindFramebuffer(GL_FRAMEBUFFER, OutputFB->Framebuffer);
glViewport(0, 0, Width, Height);
SetInitialState();
return true;
}
@ -892,10 +888,7 @@ void OpenGLSWFrameBuffer::KillNativeTexs()
bool OpenGLSWFrameBuffer::CreateFBTexture()
{
CreateTexture("FBTexture", Width, Height, 1, GL_R8, &FBTexture);
FBWidth = Width;
FBHeight = Height;
return true;
return CreateTexture("FBTexture", Width, Height, 1, GL_R8, &FBTexture);
}
//==========================================================================
@ -906,11 +899,7 @@ bool OpenGLSWFrameBuffer::CreateFBTexture()
bool OpenGLSWFrameBuffer::CreatePaletteTexture()
{
if (!CreateTexture("PaletteTexture", 256, 1, 1, GL_RGBA8, &PaletteTexture))
{
return false;
}
return true;
return CreateTexture("PaletteTexture", 256, 1, 1, GL_RGBA8, &PaletteTexture);
}
//==========================================================================
@ -942,35 +931,31 @@ bool OpenGLSWFrameBuffer::CreateVertexes()
//
//==========================================================================
void OpenGLSWFrameBuffer::CalcFullscreenCoords(FBVERTEX verts[4], bool viewarea_only, bool can_double, uint32_t color0, uint32_t color1) const
void OpenGLSWFrameBuffer::CalcFullscreenCoords(FBVERTEX verts[4], bool viewarea_only, uint32_t color0, uint32_t color1) const
{
float offset = LBOffset;//OldRenderTarget != nullptr ? 0 : LBOffset;
float top = offset - 0.5f;
float texright = float(Width) / float(FBWidth);
float texbot = float(Height) / float(FBHeight);
float mxl, mxr, myt, myb, tmxl, tmxr, tmyt, tmyb;
if (viewarea_only)
{ // Just calculate vertices for the viewarea/BlendingRect
mxl = float(BlendingRect.left) - 0.5f;
mxr = float(BlendingRect.right) - 0.5f;
myt = float(BlendingRect.top) + top;
myb = float(BlendingRect.bottom) + top;
tmxl = float(BlendingRect.left) / float(Width) * texright;
tmxr = float(BlendingRect.right) / float(Width) * texright;
tmyt = float(BlendingRect.top) / float(Height) * texbot;
tmyb = float(BlendingRect.bottom) / float(Height) * texbot;
mxl = float(BlendingRect.left);
mxr = float(BlendingRect.right);
myt = float(BlendingRect.top);
myb = float(BlendingRect.bottom);
tmxl = float(BlendingRect.left) / float(Width);
tmxr = float(BlendingRect.right) / float(Width);
tmyt = float(BlendingRect.top) / float(Height);
tmyb = float(BlendingRect.bottom) / float(Height);
}
else
{ // Calculate vertices for the whole screen
mxl = -0.5f;
mxr = float(Width << (can_double ? PixelDoubling : 0)) - 0.5f;
myt = top;
myb = float(Height << (can_double ? PixelDoubling : 0)) + top;
mxl = 0.0f;
mxr = float(Width);
myt = 0.0f;
myb = float(Height);
tmxl = 0;
tmxr = texright;
tmxr = 1.0f;
tmyt = 0;
tmyb = texbot;
tmyb = 1.0f;
}
//{ mxl, myt, 0, 1, 0, 0xFFFFFFFF, tmxl, tmyt },
@ -1210,8 +1195,6 @@ void OpenGLSWFrameBuffer::Flip()
{
assert(InScene);
DrawLetterbox();
Present();
InScene = false;
@ -1225,8 +1208,6 @@ void OpenGLSWFrameBuffer::Flip()
TrueHeight = Height;
PixelDoubling = 0;
LBOffsetI = 0;
LBOffset = 0.0f;
Reset();
V_OutputResized(Width, Height);
@ -1338,7 +1319,7 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
color0 = FlashColor0;
color1 = FlashColor1;
}
CalcFullscreenCoords(verts, Accel2D, false, color0, color1);
CalcFullscreenCoords(verts, Accel2D, color0, color1);
DrawTriangleFans(2, verts);
}
SetPixelShader(Shaders[SHADER_NormalColorPal]);
@ -1353,18 +1334,36 @@ void OpenGLSWFrameBuffer::Draw3DPart(bool copy3d)
//
//==========================================================================
void OpenGLSWFrameBuffer::DrawLetterbox()
void OpenGLSWFrameBuffer::DrawLetterbox(int x, int y, int width, int height)
{
if (LBOffsetI != 0)
int clientWidth = GetClientWidth();
int clientHeight = GetClientHeight();
if (clientWidth == 0 || clientHeight == 0)
return;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_SCISSOR_TEST);
if (x > 0)
{
glEnable(GL_SCISSOR_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glScissor(0, 0, Width, LBOffsetI);
glScissor(0, 0, clientWidth, x);
glClear(GL_COLOR_BUFFER_BIT);
glScissor(0, Height + LBOffsetI, Width, TrueHeight - Height + LBOffsetI);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
}
if (clientHeight - x - height > 0)
{
glScissor(0, x + height, clientWidth, clientHeight - x - height);
glClear(GL_COLOR_BUFFER_BIT);
}
if (y > 0)
{
glScissor(0, x, y, height);
glClear(GL_COLOR_BUFFER_BIT);
}
if (clientWidth - y - width > 0)
{
glScissor(y + width, x, clientWidth - y - width, height);
glClear(GL_COLOR_BUFFER_BIT);
}
glDisable(GL_SCISSOR_TEST);
}
void OpenGLSWFrameBuffer::UploadPalette()
@ -1604,7 +1603,7 @@ void OpenGLSWFrameBuffer::DrawPackedTextures(int packnum)
continue;
}
AddColorOnlyRect(x - 1, y - 1 - LBOffsetI, 258, 258, ColorXRGB(255, 255, 0));
AddColorOnlyRect(x - 1, y - 1, 258, 258, ColorXRGB(255, 255, 0));
int back = 0;
for (PackedTexture *box = pack->UsedList; box != nullptr; box = box->Next)
{
@ -1638,8 +1637,8 @@ void OpenGLSWFrameBuffer::DrawPackedTextures(int packnum)
quad->NumVerts = 4;
quad->NumTris = 2;
float x0 = float(x) - 0.5f;
float y0 = float(y) - 0.5f;
float x0 = float(x);
float y0 = float(y);
float x1 = x0 + 256.f;
float y1 = y0 + 256.f;
@ -1695,7 +1694,7 @@ void OpenGLSWFrameBuffer::DrawPackedTextures(int packnum)
{
x = 8;
y += 256 + 8;
if (y > TrueHeight - 256)
if (y > Height - 256)
{
return;
}
@ -2457,7 +2456,7 @@ void OpenGLSWFrameBuffer::DrawLine(int x0, int y0, int x1, int y1, int palcolor,
}
// Add the endpoints to the vertex buffer.
VertexData[VertexPos].x = float(x0);
VertexData[VertexPos].y = float(y0) + LBOffset;
VertexData[VertexPos].y = float(y0);
VertexData[VertexPos].z = 0;
VertexData[VertexPos].rhw = 1;
VertexData[VertexPos].color0 = color;
@ -2466,7 +2465,7 @@ void OpenGLSWFrameBuffer::DrawLine(int x0, int y0, int x1, int y1, int palcolor,
VertexData[VertexPos].tv = 0;
VertexData[VertexPos + 1].x = float(x1);
VertexData[VertexPos + 1].y = float(y1) + LBOffset;
VertexData[VertexPos + 1].y = float(y1);
VertexData[VertexPos + 1].z = 0;
VertexData[VertexPos + 1].rhw = 1;
VertexData[VertexPos + 1].color0 = color;
@ -2548,7 +2547,6 @@ void OpenGLSWFrameBuffer::DrawTextureParms(FTexture *img, DrawParms &parms)
double uscale = 1.f / tex->Box->Owner->Width;
bool scissoring = false;
FBVERTEX *vert;
float yoffs;
if (parms.flipX)
{
@ -2598,7 +2596,7 @@ void OpenGLSWFrameBuffer::DrawTextureParms(FTexture *img, DrawParms &parms)
BeginQuadBatch();
}
glEnable(GL_SCISSOR_TEST);
glScissor(parms.lclip, parms.uclip + LBOffsetI, parms.rclip - parms.lclip, parms.dclip - parms.uclip);
glScissor(parms.lclip, parms.uclip, parms.rclip - parms.lclip, parms.dclip - parms.uclip);
}
#endif
parms.bilinear = false;
@ -2619,23 +2617,6 @@ void OpenGLSWFrameBuffer::DrawTextureParms(FTexture *img, DrawParms &parms)
quad->NumTris = 2;
quad->NumVerts = 4;
yoffs = GatheringWipeScreen ? 0.5f : 0.5f - LBOffset;
#if 0
// Coordinates are truncated to integers, because that's effectively
// what the software renderer does. The hardware will instead round
// to nearest, it seems.
x0 = floorf(x0) - 0.5f;
y0 = floorf(y0) - yoffs;
x1 = floorf(x1) - 0.5f;
y1 = floorf(y1) - yoffs;
#else
x0 = x0 - 0.5f;
y0 = y0 - yoffs;
x1 = x1 - 0.5f;
y1 = y1 - yoffs;
#endif
vert = &VertexData[VertexPos];
// Fill the vertex buffer.
@ -2719,7 +2700,6 @@ void OpenGLSWFrameBuffer::FlatFill(int left, int top, int right, int bottom, FTe
{
return;
}
float yoffs = GatheringWipeScreen ? 0.5f : 0.5f - LBOffset;
float x0 = float(left);
float y0 = float(top);
float x1 = float(right);
@ -2732,10 +2712,6 @@ void OpenGLSWFrameBuffer::FlatFill(int left, int top, int right, int bottom, FTe
float v0 = (y0 - yo) * ith;
float u1 = (x1 - xo) * itw;
float v1 = (y1 - yo) * ith;
x0 -= 0.5f;
y0 -= yoffs;
x1 -= 0.5f;
y1 -= yoffs;
CheckQuadBatch();
@ -2824,7 +2800,7 @@ void OpenGLSWFrameBuffer::FillSimplePoly(FTexture *texture, FVector2 *points, in
BufferedTris *quad;
FBVERTEX *verts;
OpenGLTex *tex;
float yoffs, uscale, vscale;
float uscale, vscale;
int i, ipos;
uint32_t color0, color1;
float ox, oy;
@ -2890,7 +2866,6 @@ void OpenGLSWFrameBuffer::FillSimplePoly(FTexture *texture, FVector2 *points, in
quad->NumVerts = npoints;
quad->NumTris = npoints - 2;
yoffs = GatheringWipeScreen ? 0 : LBOffset;
uscale = float(1.f / (texture->GetScaledWidth() * scalex));
vscale = float(1.f / (texture->GetScaledHeight() * scaley));
ox = float(originx);
@ -2899,13 +2874,13 @@ void OpenGLSWFrameBuffer::FillSimplePoly(FTexture *texture, FVector2 *points, in
for (i = 0; i < npoints; ++i)
{
verts[i].x = points[i].X;
verts[i].y = points[i].Y + yoffs;
verts[i].y = points[i].Y;
verts[i].z = 0;
verts[i].rhw = 1;
verts[i].color0 = color0;
verts[i].color1 = color1;
float u = points[i].X - 0.5f - ox;
float v = points[i].Y - 0.5f - oy;
float u = points[i].X - ox;
float v = points[i].Y - oy;
if (dorotate)
{
float t = u;
@ -2944,8 +2919,8 @@ void OpenGLSWFrameBuffer::AddColorOnlyQuad(int left, int top, int width, int hei
quad = &QuadExtra[QuadBatchPos];
verts = &VertexData[VertexPos];
float x = float(left) - 0.5f;
float y = float(top) - 0.5f + (GatheringWipeScreen ? 0 : LBOffset);
float x = float(left);
float y = float(top);
quad->ClearSetup();
quad->ShaderNum = BQS_ColorOnly;

View file

@ -382,7 +382,7 @@ private:
bool CreatePaletteTexture();
bool CreateVertexes();
void UploadPalette();
void CalcFullscreenCoords(FBVERTEX verts[4], bool viewarea_only, bool can_double, uint32_t color0, uint32_t color1) const;
void CalcFullscreenCoords(FBVERTEX verts[4], bool viewarea_only, uint32_t color0, uint32_t color1) const;
bool Reset();
HWTexture *CopyCurrentScreen();
void ReleaseDefaultPoolItems();
@ -390,7 +390,7 @@ private:
void KillNativeTexs();
PackedTexture *AllocPackedTexture(int width, int height, bool wrapping, int format);
void DrawPackedTextures(int packnum);
void DrawLetterbox();
void DrawLetterbox(int x, int y, int width, int height);
void Draw3DPart(bool copy3d);
bool SetStyle(OpenGLTex *tex, DrawParms &parms, uint32_t &color0, uint32_t &color1, BufferedTris &quad);
static int GetStyleAlpha(int type);
@ -442,13 +442,10 @@ private:
int FlashAmount;
int TrueHeight;
int PixelDoubling;
int LBOffsetI;
float LBOffset;
float Gamma;
bool UpdatePending;
bool NeedPalUpdate;
bool NeedGammaUpdate;
int FBWidth, FBHeight;
bool VSync;
LTRBRect BlendingRect;
int In2D;

View file

@ -232,7 +232,6 @@ bool OpenGLSWFrameBuffer::WipeDo(int ticks)
EnableAlphaTest(false);
bool done = ScreenWipe->Run(ticks, this);
DrawLetterbox();
return done;
}
@ -284,7 +283,7 @@ void OpenGLSWFrameBuffer::Wiper::DrawScreen(OpenGLSWFrameBuffer *fb, HWTexture *
{
FBVERTEX verts[4];
fb->CalcFullscreenCoords(verts, false, false, color0, color1);
fb->CalcFullscreenCoords(verts, false, color0, color1);
fb->SetTexture(0, tex);
fb->SetAlphaBlend(blendop, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
fb->SetPixelShader(fb->Shaders[SHADER_NormalColor]);
@ -410,15 +409,15 @@ bool OpenGLSWFrameBuffer::Wiper_Melt::Run(int ticks, OpenGLSWFrameBuffer *fb)
quad->NumTris = 2;
// Fill the vertex buffer.
float u0 = rect.left / float(fb->FBWidth);
float u0 = rect.left / float(fb->Width);
float v0 = 0;
float u1 = rect.right / float(fb->FBWidth);
float v1 = (rect.bottom - rect.top) / float(fb->FBHeight);
float u1 = rect.right / float(fb->Width);
float v1 = (rect.bottom - rect.top) / float(fb->Height);
float x0 = float(rect.left) - 0.5f;
float x1 = float(rect.right) - 0.5f;
float y0 = float(dpt.y + fb->LBOffsetI) - 0.5f;
float y1 = float(fbheight + fb->LBOffsetI) - 0.5f;
float x0 = float(rect.left);
float x1 = float(rect.right);
float y0 = float(dpt.y);
float y1 = float(fbheight);
vert[0].x = x0;
vert[0].y = y0;
@ -562,18 +561,15 @@ bool OpenGLSWFrameBuffer::Wiper_Burn::Run(int ticks, OpenGLSWFrameBuffer *fb)
DrawScreen(fb, fb->InitialWipeScreen);
// Burn the new screen on top of it.
float top = fb->LBOffset - 0.5f;
float right = float(fb->Width) - 0.5f;
float bot = float(fb->Height) + top;
float texright = float(fb->Width) / float(fb->FBWidth);
float texbot = float(fb->Height) / float(fb->FBHeight);
float right = float(fb->Width);
float bot = float(fb->Height);
BURNVERTEX verts[4] =
{
{ -0.5f, top, 0.5f, 1.f, 0.f, 0.f, 0, 0 },
{ right, top, 0.5f, 1.f, texright, 0.f, 1, 0 },
{ right, bot, 0.5f, 1.f, texright, texbot, 1, 1 },
{ -0.5f, bot, 0.5f, 1.f, 0.f, texbot, 0, 1 }
{ 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0, 0 },
{ right, 0.f, 0.f, 1.f, 1.f, 0.f, 1, 0 },
{ right, bot, 0.f, 1.f, 1.f, 1.f, 1, 1 },
{ 0.f, bot, 0.f, 1.f, 0.f, 1.f, 0, 1 }
};
fb->SetTexture(0, fb->FinalWipeScreen);