Remove GetTrueHeight from GL renderer and concentrate all viewport calculations in SetOutputViewport

This commit is contained in:
Magnus Norddahl 2016-08-12 07:28:29 +02:00 committed by Christoph Oelckers
parent 353a464f5b
commit c817979eae
9 changed files with 163 additions and 138 deletions

View File

@ -155,14 +155,10 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms)
color.a = (BYTE)(parms.Alpha * 255);
// scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates
int btm = (SCREENHEIGHT - screen->GetHeight()) / 2;
btm = SCREENHEIGHT - btm;
int space = (static_cast<OpenGLFrameBuffer*>(screen)->GetTrueHeight() - screen->GetHeight()) / 2;
dg.mScissor[0] = parms.lclip;
dg.mScissor[1] = btm - parms.dclip + space;
dg.mScissor[2] = parms.rclip - parms.lclip;
dg.mScissor[3] = parms.dclip - parms.uclip;
dg.mScissor[0] = GLRenderer->ScreenToWindowX(parms.lclip);
dg.mScissor[1] = GLRenderer->ScreenToWindowY(parms.dclip);
dg.mScissor[2] = GLRenderer->ScreenToWindowX(parms.rclip) - GLRenderer->ScreenToWindowX(parms.lclip);
dg.mScissor[3] = GLRenderer->ScreenToWindowY(parms.dclip) - GLRenderer->ScreenToWindowY(parms.uclip);
FSimpleVertex *ptr = &mVertices[dg.mVertIndex];
ptr->Set(x, y, 0, u1, v1, color); ptr++;
@ -438,7 +434,8 @@ void F2DDrawer::Flush()
glDrawArrays(GL_TRIANGLE_STRIP, dt->mVertIndex + 4, 4);
}
glScissor(0, 0, screen->GetWidth(), screen->GetHeight());
const auto &viewport = GLRenderer->mScreenViewport;
glScissor(viewport.left, viewport.top, viewport.width, viewport.height);
glDisable(GL_SCISSOR_TEST);
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_RenderState.SetTextureMode(TM_MODULATE);

View File

@ -182,7 +182,7 @@ void FGLRenderer::BloomScene()
// Add bloom back to scene texture:
mBuffers->BindCurrentFB();
glViewport(mOutputViewport.left, mOutputViewport.top, mOutputViewport.width, mOutputViewport.height);
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
@ -243,7 +243,7 @@ void FGLRenderer::LensDistortScene()
0.0f
};
float aspect = mOutputViewport.width / mOutputViewport.height;
float aspect = mSceneViewport.width / mSceneViewport.height;
// Scale factor to keep sampling within the input texture
float r2 = aspect * aspect * 0.25 + 0.25f;
@ -283,60 +283,21 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
if (FGLRenderBuffers::IsEnabled())
{
FGLPostProcessState savedState;
mBuffers->BindOutputFB();
int x, y, width, height;
GL_IRECT box;
if (bounds)
{
x = bounds->left;
y = bounds->top;
width = bounds->width;
height = bounds->height;
box = *bounds;
}
else
{
// Calculate letterbox
int clientWidth = framebuffer->GetClientWidth();
int clientHeight = framebuffer->GetClientHeight();
float scaleX = clientWidth / (float)mScreenViewport.width;
float scaleY = clientHeight / (float)mScreenViewport.height;
float scale = MIN(scaleX, scaleY);
width = (int)round(mScreenViewport.width * scale);
height = (int)round(mScreenViewport.height * scale);
x = (clientWidth - width) / 2;
y = (clientHeight - height) / 2;
// Black bars around the box:
glViewport(0, 0, clientWidth, clientHeight);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_SCISSOR_TEST);
if (y > 0)
{
glScissor(0, 0, clientWidth, y);
glClear(GL_COLOR_BUFFER_BIT);
}
if (clientHeight - y - height > 0)
{
glScissor(0, y + height, clientWidth, clientHeight - y - height);
glClear(GL_COLOR_BUFFER_BIT);
}
if (x > 0)
{
glScissor(0, y, x, height);
glClear(GL_COLOR_BUFFER_BIT);
}
if (clientWidth - x - width > 0)
{
glScissor(x + width, y, clientWidth - x - width, height);
glClear(GL_COLOR_BUFFER_BIT);
}
ClearBorders();
box = mOutputLetterbox;
}
glDisable(GL_SCISSOR_TEST);
// Present what was rendered:
glViewport(x, y, width, height);
glDisable(GL_BLEND);
glViewport(box.left, box.top, box.width, box.height);
mPresentShader->Bind();
mPresentShader->InputTexture.Set(0);
@ -358,4 +319,48 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
RenderScreenQuad();
}
else if (!bounds)
{
FGLPostProcessState savedState;
ClearBorders();
}
}
//-----------------------------------------------------------------------------
//
// Fills the black bars around the screen letterbox
//
//-----------------------------------------------------------------------------
void FGLRenderer::ClearBorders()
{
const auto &box = mOutputLetterbox;
int clientWidth = framebuffer->GetClientWidth();
int clientHeight = framebuffer->GetClientHeight();
glViewport(0, 0, clientWidth, clientHeight);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_SCISSOR_TEST);
if (box.top > 0)
{
glScissor(0, 0, clientWidth, box.top);
glClear(GL_COLOR_BUFFER_BIT);
}
if (clientHeight - box.top - box.height > 0)
{
glScissor(0, box.top + box.height, clientWidth, clientHeight - box.top - box.height);
glClear(GL_COLOR_BUFFER_BIT);
}
if (box.left > 0)
{
glScissor(0, box.top, box.left, box.height);
glClear(GL_COLOR_BUFFER_BIT);
}
if (clientWidth - box.left - box.width > 0)
{
glScissor(box.left + box.width, box.top, clientWidth - box.left - box.width, box.height);
glClear(GL_COLOR_BUFFER_BIT);
}
glDisable(GL_SCISSOR_TEST);
}

View File

@ -79,6 +79,8 @@
EXTERN_CVAR(Int, screenblocks)
CVAR(Bool, gl_scale_viewport, true, 0);
//===========================================================================
//
// Renderer interface
@ -190,16 +192,14 @@ void FGLRenderer::SetOutputViewport(GL_IRECT *bounds)
{
if (bounds)
{
mOutputViewport = *bounds;
mOutputViewportLB = *bounds;
mSceneViewport = *bounds;
mScreenViewport = *bounds;
mOutputLetterbox = *bounds;
return;
}
int height, width;
// Special handling so the view with a visible status bar displays properly
int height, width;
if (screenblocks >= 10)
{
height = framebuffer->GetHeight();
@ -211,29 +211,64 @@ void FGLRenderer::SetOutputViewport(GL_IRECT *bounds)
width = (screenblocks*framebuffer->GetWidth() / 10);
}
int trueheight = framebuffer->GetTrueHeight(); // ugh...
int bars = (trueheight - framebuffer->GetHeight()) / 2;
int vw = viewwidth;
int vh = viewheight;
// Back buffer letterbox for the final output
int clientWidth = framebuffer->GetClientWidth();
int clientHeight = framebuffer->GetClientHeight();
int screenWidth = framebuffer->GetWidth();
int screenHeight = framebuffer->GetHeight();
float scale = MIN(clientWidth / (float)screenWidth, clientHeight / (float)screenHeight);
mOutputLetterbox.width = (int)round(screenWidth * scale);
mOutputLetterbox.height = (int)round(screenHeight * scale);
mOutputLetterbox.left = (clientWidth - mOutputLetterbox.width) / 2;
mOutputLetterbox.top = (clientHeight - mOutputLetterbox.height) / 2;
// The entire renderable area, including the 2D HUD
mScreenViewport.left = 0;
mScreenViewport.top = 0;
mScreenViewport.width = framebuffer->GetWidth();
mScreenViewport.height = framebuffer->GetHeight();
mScreenViewport.width = screenWidth;
mScreenViewport.height = screenHeight;
// Letterboxed viewport for the main scene
mOutputViewportLB.left = viewwindowx;
mOutputViewportLB.top = trueheight - bars - (height + viewwindowy - ((height - vh) / 2));
mOutputViewportLB.width = vw;
mOutputViewportLB.height = height;
// Viewport for the 3D scene
mSceneViewport.left = viewwindowx;
mSceneViewport.top = screenHeight - (height + viewwindowy - ((height - viewheight) / 2));
mSceneViewport.width = viewwidth;
mSceneViewport.height = height;
// Entire canvas for player sprites
mOutputViewport.left = 0;
mOutputViewport.top = (trueheight - framebuffer->GetHeight()) / 2;
mOutputViewport.width = framebuffer->GetWidth();
mOutputViewport.height = framebuffer->GetHeight();
// Scale viewports to fit letterbox
if (gl_scale_viewport || !FGLRenderBuffers::IsEnabled())
{
mScreenViewport.width = mOutputLetterbox.width;
mScreenViewport.height = mOutputLetterbox.height;
mSceneViewport.left = (int)round(mSceneViewport.left * scale);
mSceneViewport.top = (int)round(mSceneViewport.top * scale);
mSceneViewport.width = (int)round(mSceneViewport.width * scale);
mSceneViewport.height = (int)round(mSceneViewport.height * scale);
// Without render buffers we have to render directly to the letterbox
if (!FGLRenderBuffers::IsEnabled())
{
mScreenViewport.left += mOutputLetterbox.left;
mScreenViewport.top += mOutputLetterbox.top;
mSceneViewport.left += mOutputLetterbox.left;
mSceneViewport.top += mOutputLetterbox.top;
}
}
}
//===========================================================================
//
// Calculates the OpenGL window coordinates for a zdoom screen position
//
//===========================================================================
int FGLRenderer::ScreenToWindowX(int x)
{
return mScreenViewport.left + (int)round(x * mScreenViewport.width / (float)framebuffer->GetWidth());
}
int FGLRenderer::ScreenToWindowY(int y)
{
return mScreenViewport.top + mScreenViewport.height - (int)round(y * mScreenViewport.height / (float)framebuffer->GetHeight());
}
//===========================================================================
@ -258,6 +293,7 @@ void FGLRenderer::Begin2D()
mBuffers->BindCurrentFB();
}
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
glScissor(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
gl_RenderState.EnableFog(false);
gl_RenderState.Set2DMode(true);
@ -363,32 +399,3 @@ unsigned char *FGLRenderer::GetTextureBuffer(FTexture *tex, int &w, int &h)
}
return NULL;
}
//===========================================================================
//
//
//
//===========================================================================
void FGLRenderer::ClearBorders()
{
OpenGLFrameBuffer *glscreen = static_cast<OpenGLFrameBuffer*>(screen);
// Letterbox time! Draw black top and bottom borders.
int width = glscreen->GetWidth();
int height = glscreen->GetHeight();
int trueHeight = glscreen->GetTrueHeight();
int borderHeight = (trueHeight - height) / 2;
glViewport(0, 0, width, trueHeight);
glClearColor(0, 0, 0, 1);
glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, width, borderHeight);
glClear(GL_COLOR_BUFFER_BIT);
glScissor(0, trueHeight-borderHeight, width, borderHeight);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
glViewport(0, (trueHeight - height) / 2, width, height);
}

View File

@ -111,17 +111,20 @@ public:
F2DDrawer *m2DDrawer;
GL_IRECT mScreenViewport;
GL_IRECT mOutputViewportLB;
GL_IRECT mOutputViewport;
GL_IRECT mSceneViewport;
GL_IRECT mOutputLetterbox;
bool mDrawingScene2D = false;
float mCameraExposure = 1.0f;
FGLRenderer(OpenGLFrameBuffer *fb);
~FGLRenderer() ;
void SetOutputViewport(GL_IRECT *bounds);
int ScreenToWindowX(int x);
int ScreenToWindowY(int y);
angle_t FrustumAngle();
void SetViewArea();
void SetOutputViewport(GL_IRECT *bounds);
void Set3DViewport(bool mainview);
void Reset3DViewport();
sector_t *RenderViewpoint (AActor * camera, GL_IRECT * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen);

View File

@ -157,7 +157,7 @@ void FGLRenderer::SetViewArea()
void FGLRenderer::Reset3DViewport()
{
glViewport(mOutputViewport.left, mOutputViewport.top, mOutputViewport.width, mOutputViewport.height);
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
}
//-----------------------------------------------------------------------------
@ -170,11 +170,11 @@ void FGLRenderer::Set3DViewport(bool mainview)
{
if (mainview && FGLRenderBuffers::IsEnabled())
{
mBuffers->Setup(mOutputViewport.width, mOutputViewport.height);
mBuffers->Setup(mScreenViewport.width, mScreenViewport.height);
mBuffers->BindSceneFB();
}
const auto &bounds = mOutputViewportLB;
const auto &bounds = mSceneViewport;
glViewport(bounds.left, bounds.top, bounds.width, bounds.height);
glScissor(bounds.left, bounds.top, bounds.width, bounds.height);

View File

@ -160,10 +160,6 @@ void OpenGLFrameBuffer::InitializeState()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//int trueH = GetTrueHeight();
//int h = GetHeight();
//glViewport(0, (trueH - h)/2, GetWidth(), GetHeight());
GLRenderer->Initialize(GetWidth(), GetHeight());
GLRenderer->SetOutputViewport(nullptr);
Begin2D(false);
@ -191,13 +187,6 @@ void OpenGLFrameBuffer::Update()
DrawRateStuff();
GLRenderer->Flush();
if (GetTrueHeight() != GetHeight())
{
if (GLRenderer != NULL)
GLRenderer->ClearBorders();
Begin2D(false);
}
if (gl_draw_sync || !swapped)
{
Swap();
@ -484,15 +473,41 @@ void OpenGLFrameBuffer::FillSimplePoly(FTexture *texture, FVector2 *points, int
void OpenGLFrameBuffer::GetScreenshotBuffer(const BYTE *&buffer, int &pitch, ESSType &color_type)
{
const auto &viewport = GLRenderer->mScreenViewport;
// Grab what is in the back buffer.
// We cannot rely on SCREENWIDTH/HEIGHT here because the output may have been scaled.
TArray<uint8_t> pixels;
pixels.Resize(viewport.width * viewport.height);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(viewport.left, viewport.top, viewport.width, viewport.height, GL_RGB, GL_UNSIGNED_BYTE, &pixels[0]);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
// Copy to screenshot buffer:
int w = SCREENWIDTH;
int h = SCREENHEIGHT;
ReleaseScreenshotBuffer();
ScreenshotBuffer = new BYTE[w * h * 3];
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0,(GetTrueHeight() - GetHeight()) / 2,w,h,GL_RGB,GL_UNSIGNED_BYTE,ScreenshotBuffer);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
float rcpWidth = 1.0f / viewport.width;
float rcpHeight = 1.0f / viewport.height;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
float u = (x + 0.5f) * rcpWidth;
float v = (y + 0.5f) * rcpHeight;
int sx = u * viewport.width;
int sy = v * viewport.height;
int sindex = (sx + sy * w) * 3;
int dindex = (x + y * w) * 3;
ScreenshotBuffer[dindex] = pixels[sindex];
ScreenshotBuffer[dindex + 1] = pixels[sindex + 1];
ScreenshotBuffer[dindex + 2] = pixels[sindex + 2];
}
}
pitch = -w*3;
color_type = SS_RGB;
buffer = ScreenshotBuffer + w * 3 * (h - 1);

View File

@ -151,8 +151,9 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type)
return false;
}
wipestartscreen = new FHardwareTexture(Width, Height, true);
wipestartscreen->CreateTexture(NULL, Width, Height, 0, false, 0);
const auto &viewport = GLRenderer->mScreenViewport;
wipestartscreen = new FHardwareTexture(viewport.width, viewport.height, true);
wipestartscreen->CreateTexture(NULL, viewport.width, viewport.height, 0, false, 0);
GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1);
GLRenderer->mSamplerManager->Bind(1, CLAMP_NONE, -1);
glFinish();
@ -161,14 +162,14 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type)
if (FGLRenderBuffers::IsEnabled())
{
GLRenderer->mBuffers->BindCurrentFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
}
else
{
GLint readbuffer = 0;
glGetIntegerv(GL_READ_BUFFER, &readbuffer);
glReadBuffer(GL_FRONT);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
glReadBuffer(readbuffer);
}
@ -189,8 +190,10 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type)
void OpenGLFrameBuffer::WipeEndScreen()
{
GLRenderer->m2DDrawer->Flush();
wipeendscreen = new FHardwareTexture(Width, Height, true);
wipeendscreen->CreateTexture(NULL, Width, Height, 0, false, 0);
const auto &viewport = GLRenderer->mScreenViewport;
wipeendscreen = new FHardwareTexture(viewport.width, viewport.height, true);
wipeendscreen->CreateTexture(NULL, viewport.width, viewport.height, 0, false, 0);
GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1);
glFinish();
wipeendscreen->Bind(0, false, false);
@ -198,7 +201,7 @@ void OpenGLFrameBuffer::WipeEndScreen()
if (FGLRenderBuffers::IsEnabled())
GLRenderer->mBuffers->BindCurrentFB();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

View File

@ -65,8 +65,6 @@ public:
int GetClientWidth();
int GetClientHeight();
int GetTrueHeight() { return GetHeight(); }
protected:
int m_lock;
bool m_isUpdatePending;

View File

@ -61,9 +61,6 @@ public:
int GetClientWidth();
int GetClientHeight();
//[C]
int GetTrueHeight() { return GetHeight();}
protected:
bool CanUpdate();
void SetGammaTable(WORD *tbl);