diff --git a/src/gl/dynlights/gl_shadowmap.cpp b/src/gl/dynlights/gl_shadowmap.cpp index 26bb32a7c..87d3c5218 100644 --- a/src/gl/dynlights/gl_shadowmap.cpp +++ b/src/gl/dynlights/gl_shadowmap.cpp @@ -60,7 +60,7 @@ void FShadowMap::Update() glViewport(0, 0, gl_shadowmap_quality, 1024); GLRenderer->RenderScreenQuad(); - const auto &viewport = GLRenderer->mScreenViewport; + const auto &viewport = screen->mScreenViewport; glViewport(viewport.left, viewport.top, viewport.width, viewport.height); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, 0); diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index 5b2a6f0d7..00658351c 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -187,6 +187,9 @@ void FGLRenderer::AmbientOccludeScene() float blurSharpness = 1.0f / blurAmount; + const auto &mSceneViewport = screen->mSceneViewport; + const auto &mScreenViewport = screen->mScreenViewport; + float sceneScaleX = mSceneViewport.width / (float)mScreenViewport.width; float sceneScaleY = mSceneViewport.height / (float)mScreenViewport.height; float sceneOffsetX = mSceneViewport.left / (float)mScreenViewport.width; @@ -254,7 +257,7 @@ void FGLRenderer::AmbientOccludeScene() // Add SSAO back to scene texture: mBuffers->BindSceneFB(false); - glViewport(mSceneViewport.left, mSceneViewport.top, mSceneViewport.width, mSceneViewport.height); + glViewport(screen->mSceneViewport.left, screen->mSceneViewport.top, screen->mSceneViewport.width, screen->mSceneViewport.height); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -292,6 +295,9 @@ void FGLRenderer::UpdateCameraExposure() FGLPostProcessState savedState; savedState.SaveTextureBindings(2); + const auto &mSceneViewport = screen->mSceneViewport; + const auto &mScreenViewport = screen->mScreenViewport; + // Extract light level from scene texture: auto &level0 = mBuffers->ExposureLevels[0]; level0.Framebuffer.Bind(); @@ -365,6 +371,9 @@ void FGLRenderer::BloomScene(int fixedcm) auto &level0 = mBuffers->BloomLevels[0]; + const auto &mSceneViewport = screen->mSceneViewport; + const auto &mScreenViewport = screen->mScreenViewport; + // Extract blooming pixels from scene texture: level0.VFramebuffer.Bind(); glViewport(0, 0, level0.Width, level0.Height); @@ -450,7 +459,7 @@ void FGLRenderer::BlurScene(float gameinfobluramount) int numLevels = 3; // Must be 4 or less (since FGLRenderBuffers::NumBloomLevels is 4 and we are using its buffers). assert(numLevels <= FGLRenderBuffers::NumBloomLevels); - const auto &viewport = mScreenViewport; // The area we want to blur. Could also be mSceneViewport if only the scene area is to be blured + const auto &viewport = screen->mScreenViewport; // The area we want to blur. Could also be mSceneViewport if only the scene area is to be blured const auto &level0 = mBuffers->BloomLevels[0]; @@ -490,7 +499,7 @@ void FGLRenderer::BlurScene(float gameinfobluramount) // Copy blur back to scene texture: mBuffers->BlitLinear(level0.VFramebuffer, mBuffers->GetCurrentFB(), 0, 0, level0.Width, level0.Height, viewport.left, viewport.top, viewport.width, viewport.height); - glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); + glViewport(viewport.left, viewport.top, viewport.width, viewport.height); FGLDebug::PopGroup(); } @@ -639,7 +648,7 @@ void FGLRenderer::LensDistortScene() 0.0f }; - float aspect = mSceneViewport.width / (float)mSceneViewport.height; + float aspect = screen->mSceneViewport.width / (float)screen->mSceneViewport.height; // Scale factor to keep sampling within the input texture float r2 = aspect * aspect * 0.25 + 0.25f; @@ -715,6 +724,8 @@ void FGLRenderer::ApplyFXAA() void FGLRenderer::Flush() { const s3d::Stereo3DMode& stereo3dMode = s3d::Stereo3DMode::getCurrentMode(); + const auto &mSceneViewport = screen->mSceneViewport; + const auto &mScreenViewport = screen->mScreenViewport; if (stereo3dMode.IsMono() || !FGLRenderBuffers::IsEnabled()) { @@ -747,7 +758,7 @@ void FGLRenderer::Flush() // //----------------------------------------------------------------------------- -void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma) +void FGLRenderer::CopyToBackbuffer(const IntRect *bounds, bool applyGamma) { screen->Draw2D(); // draw all pending 2D stuff before copying the buffer screen->Clear2D(); @@ -760,7 +771,7 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma) FGLPostProcessState savedState; mBuffers->BindOutputFB(); - GL_IRECT box; + IntRect box; if (bounds) { box = *bounds; @@ -768,7 +779,7 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma) else { ClearBorders(); - box = mOutputLetterbox; + box = screen->mOutputLetterbox; } mBuffers->BindCurrentTexture(0); @@ -782,7 +793,7 @@ void FGLRenderer::CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma) FGLDebug::PopGroup(); } -void FGLRenderer::DrawPresentTexture(const GL_IRECT &box, bool applyGamma) +void FGLRenderer::DrawPresentTexture(const IntRect &box, bool applyGamma) { glViewport(box.left, box.top, box.width, box.height); @@ -815,7 +826,7 @@ void FGLRenderer::DrawPresentTexture(const GL_IRECT &box, bool applyGamma) mPresentShader->Saturation.Set(clamp(vid_saturation, -15.0f, 15.f)); mPresentShader->GrayFormula.Set(static_cast(gl_satformula)); } - mPresentShader->Scale.Set(mScreenViewport.width / (float)mBuffers->GetWidth(), mScreenViewport.height / (float)mBuffers->GetHeight()); + mPresentShader->Scale.Set(screen->mScreenViewport.width / (float)mBuffers->GetWidth(), screen->mScreenViewport.height / (float)mBuffers->GetHeight()); RenderScreenQuad(); } @@ -827,7 +838,7 @@ void FGLRenderer::DrawPresentTexture(const GL_IRECT &box, bool applyGamma) void FGLRenderer::ClearBorders() { - const auto &box = mOutputLetterbox; + const auto &box = screen->mOutputLetterbox; int clientWidth = framebuffer->GetClientWidth(); int clientHeight = framebuffer->GetClientHeight(); diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index a826d4dc6..614384205 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -67,7 +67,6 @@ EXTERN_CVAR(Int, screenblocks) EXTERN_CVAR(Bool, cl_capfps) -CVAR(Bool, gl_scale_viewport, true, CVAR_ARCHIVE); extern bool NoInterpolateView; //=========================================================================== @@ -225,117 +224,6 @@ FGLRenderer::~FGLRenderer() delete mFXAALumaShader; } -//========================================================================== -// -// Calculates the viewport values needed for 2D and 3D operations -// -//========================================================================== - -void FGLRenderer::SetOutputViewport(GL_IRECT *bounds) -{ - if (bounds) - { - mSceneViewport = *bounds; - mScreenViewport = *bounds; - mOutputLetterbox = *bounds; - return; - } - - // Special handling so the view with a visible status bar displays properly - int height, width; - if (screenblocks >= 10) - { - height = framebuffer->GetHeight(); - width = framebuffer->GetWidth(); - } - else - { - height = (screenblocks*framebuffer->GetHeight() / 10) & ~7; - width = (screenblocks*framebuffer->GetWidth() / 10); - } - - // Back buffer letterbox for the final output - int clientWidth = framebuffer->GetClientWidth(); - int clientHeight = framebuffer->GetClientHeight(); - if (clientWidth == 0 || clientHeight == 0) - { - // When window is minimized there may not be any client area. - // Pretend to the rest of the render code that we just have a very small window. - clientWidth = 160; - clientHeight = 120; - } - int screenWidth = framebuffer->GetWidth(); - int screenHeight = framebuffer->GetHeight(); - float scaleX, scaleY; - if (ViewportIsScaled43()) - { - scaleX = MIN(clientWidth / (float)screenWidth, clientHeight / (screenHeight * 1.2f)); - scaleY = scaleX * 1.2f; - } - else - { - scaleX = MIN(clientWidth / (float)screenWidth, clientHeight / (float)screenHeight); - scaleY = scaleX; - } - mOutputLetterbox.width = (int)round(screenWidth * scaleX); - mOutputLetterbox.height = (int)round(screenHeight * scaleY); - 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 = screenWidth; - mScreenViewport.height = screenHeight; - - // Viewport for the 3D scene - mSceneViewport.left = viewwindowx; - mSceneViewport.top = screenHeight - (height + viewwindowy - ((height - viewheight) / 2)); - mSceneViewport.width = viewwidth; - mSceneViewport.height = height; - - // Scale viewports to fit letterbox - bool notScaled = ((mScreenViewport.width == ViewportScaledWidth(mScreenViewport.width, mScreenViewport.height)) && - (mScreenViewport.width == ViewportScaledHeight(mScreenViewport.width, mScreenViewport.height)) && - !ViewportIsScaled43()); - if ((gl_scale_viewport && !framebuffer->IsFullscreen() && notScaled) || !FGLRenderBuffers::IsEnabled()) - { - mScreenViewport.width = mOutputLetterbox.width; - mScreenViewport.height = mOutputLetterbox.height; - mSceneViewport.left = (int)round(mSceneViewport.left * scaleX); - mSceneViewport.top = (int)round(mSceneViewport.top * scaleY); - mSceneViewport.width = (int)round(mSceneViewport.width * scaleX); - mSceneViewport.height = (int)round(mSceneViewport.height * scaleY); - - // 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; - } - } - - s3d::Stereo3DMode::getCurrentMode().AdjustViewports(); -} - -//=========================================================================== -// -// 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()); -} - //=========================================================================== // // @@ -482,7 +370,7 @@ void FGLRenderer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, doub gltex->BindToFrameBuffer(); } - GL_IRECT bounds; + IntRect bounds; bounds.left = bounds.top = 0; bounds.width = FHardwareTexture::GetTexDimension(gltex->GetWidth()); bounds.height = FHardwareTexture::GetTexDimension(gltex->GetHeight()); @@ -516,7 +404,7 @@ void FGLRenderer::WriteSavePic(player_t *player, FileWriter *file, int width, in void FGLRenderer::BeginFrame() { - buffersActive = GLRenderer->mBuffers->Setup(GLRenderer->mScreenViewport.width, GLRenderer->mScreenViewport.height, GLRenderer->mSceneViewport.width, GLRenderer->mSceneViewport.height); + buffersActive = GLRenderer->mBuffers->Setup(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); } //=========================================================================== @@ -579,6 +467,7 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer) { mBuffers->BindCurrentFB(); } + const auto &mScreenViewport = screen->mScreenViewport; glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); gl_RenderState.mViewMatrix.loadIdentity(); @@ -641,10 +530,10 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer) glEnable(GL_SCISSOR_TEST); // scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates // Note that the origin here is the lower left corner! - auto sciX = ScreenToWindowX(cmd.mScissor[0]); - auto sciY = ScreenToWindowY(cmd.mScissor[3]); - auto sciW = ScreenToWindowX(cmd.mScissor[2]) - sciX; - auto sciH = ScreenToWindowY(cmd.mScissor[1]) - sciY; + auto sciX = screen->ScreenToWindowX(cmd.mScissor[0]); + auto sciY = screen->ScreenToWindowY(cmd.mScissor[3]); + auto sciW = screen->ScreenToWindowX(cmd.mScissor[2]) - sciX; + auto sciH = screen->ScreenToWindowY(cmd.mScissor[1]) - sciY; glScissor(sciX, sciY, sciW, sciH); } else glDisable(GL_SCISSOR_TEST); diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 51fa30276..d3ac02671 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -51,19 +51,6 @@ class FCustomPostProcessShaders; class GLSceneDrawer; class SWSceneDrawer; -struct GL_IRECT -{ - int left,top; - int width,height; - - - void Offset(int xofs,int yofs) - { - left+=xofs; - top+=yofs; - } -}; - enum { DM_MAINVIEW, @@ -147,9 +134,6 @@ public: SWSceneDrawer *swdrawer = nullptr; LegacyShaderContainer *legacyShaders = nullptr; - GL_IRECT mScreenViewport; - GL_IRECT mSceneViewport; - GL_IRECT mOutputLetterbox; bool mDrawingScene2D = false; bool buffersActive = false; @@ -160,10 +144,6 @@ public: FGLRenderer(OpenGLFrameBuffer *fb); ~FGLRenderer() ; - void SetOutputViewport(GL_IRECT *bounds); - int ScreenToWindowX(int x); - int ScreenToWindowY(int y); - void Initialize(int width, int height); void ClearBorders(); @@ -184,8 +164,8 @@ public: void LensDistortScene(); void ApplyFXAA(); void BlurScene(float gameinfobluramount); - void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma); - void DrawPresentTexture(const GL_IRECT &box, bool applyGamma); + void CopyToBackbuffer(const IntRect *bounds, bool applyGamma); + void DrawPresentTexture(const IntRect &box, bool applyGamma); void Flush(); void Draw2D(F2DDrawer *data); void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index e440e6d0b..823da8b33 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -123,7 +123,7 @@ void GLSceneDrawer::SetViewArea() void GLSceneDrawer::Reset3DViewport() { - glViewport(GLRenderer->mScreenViewport.left, GLRenderer->mScreenViewport.top, GLRenderer->mScreenViewport.width, GLRenderer->mScreenViewport.height); + glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height); } //----------------------------------------------------------------------------- @@ -150,7 +150,7 @@ void GLSceneDrawer::Set3DViewport(bool mainview) glClearColor(GLRenderer->mSceneClearColor[0], GLRenderer->mSceneClearColor[1], GLRenderer->mSceneClearColor[2], 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - const auto &bounds = GLRenderer->mSceneViewport; + const auto &bounds = screen->mSceneViewport; glViewport(bounds.left, bounds.top, bounds.width, bounds.height); glScissor(bounds.left, bounds.top, bounds.width, bounds.height); @@ -637,7 +637,7 @@ void GLSceneDrawer::SetFixedColormap (player_t *player) // //----------------------------------------------------------------------------- -sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen) +sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen) { sector_t * lviewsector; GLRenderer->mSceneClearColor[0] = 0.0f; @@ -680,7 +680,7 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f SetFixedColormap(camera->player); // reiterate color map for each eye, so night vision goggles work in both eyes const s3d::EyePose * eye = stereo3dMode.getEyePose(eye_ix); eye->SetUp(); - GLRenderer->SetOutputViewport(bounds); + screen->SetOutputViewport(bounds); Set3DViewport(mainview); GLRenderer->mDrawingScene2D = true; GLRenderer->mCurrentFoV = fov; @@ -704,12 +704,12 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f // This should be done after postprocessing, not before. GLRenderer->mBuffers->BindCurrentFB(); - glViewport(GLRenderer->mScreenViewport.left, GLRenderer->mScreenViewport.top, GLRenderer->mScreenViewport.width, GLRenderer->mScreenViewport.height); + glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height); if (!toscreen) { gl_RenderState.mViewMatrix.loadIdentity(); - gl_RenderState.mProjectionMatrix.ortho(GLRenderer->mScreenViewport.left, GLRenderer->mScreenViewport.width, GLRenderer->mScreenViewport.height, GLRenderer->mScreenViewport.top, -1.0f, 1.0f); + gl_RenderState.mProjectionMatrix.ortho(screen->mScreenViewport.left, screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mScreenViewport.top, -1.0f, 1.0f); gl_RenderState.ApplyMatrices(); } } @@ -733,7 +733,7 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f void GLSceneDrawer::WriteSavePic (player_t *player, FileWriter *file, int width, int height) { - GL_IRECT bounds; + IntRect bounds; P_FindParticleSubsectors(); // make sure that all recently spawned particles have a valid subsector. bounds.left=0; diff --git a/src/gl/scene/gl_scenedrawer.h b/src/gl/scene/gl_scenedrawer.h index 94b872c4f..cc712c4ac 100644 --- a/src/gl/scene/gl_scenedrawer.h +++ b/src/gl/scene/gl_scenedrawer.h @@ -63,7 +63,7 @@ public: void EndDrawScene(sector_t * viewsector); void DrawEndScene2D(sector_t * viewsector); - sector_t *RenderViewpoint(AActor * camera, GL_IRECT * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); + sector_t *RenderViewpoint(AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); sector_t *RenderView(player_t *player); void WriteSavePic(player_t *player, FileWriter *file, int width, int height); diff --git a/src/gl/stereo3d/gl_anaglyph.cpp b/src/gl/stereo3d/gl_anaglyph.cpp index 8aaa0e72d..791c49982 100644 --- a/src/gl/stereo3d/gl_anaglyph.cpp +++ b/src/gl/stereo3d/gl_anaglyph.cpp @@ -45,12 +45,12 @@ void MaskAnaglyph::Present() const gl_RenderState.SetColorMask(leftEye.GetColorMask().r, leftEye.GetColorMask().g, leftEye.GetColorMask().b, true); gl_RenderState.ApplyColorMask(); GLRenderer->mBuffers->BindEyeTexture(0, 0); - GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true); gl_RenderState.SetColorMask(rightEye.GetColorMask().r, rightEye.GetColorMask().g, rightEye.GetColorMask().b, true); gl_RenderState.ApplyColorMask(); GLRenderer->mBuffers->BindEyeTexture(1, 0); - GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true); gl_RenderState.ResetColorMask(); gl_RenderState.ApplyColorMask(); diff --git a/src/gl/stereo3d/gl_interleaved3d.cpp b/src/gl/stereo3d/gl_interleaved3d.cpp index 9cb9be870..804eea6d1 100644 --- a/src/gl/stereo3d/gl_interleaved3d.cpp +++ b/src/gl/stereo3d/gl_interleaved3d.cpp @@ -92,7 +92,7 @@ static void prepareInterleavedPresent(FPresentStereoShaderBase& shader) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - const GL_IRECT& box = GLRenderer->mOutputLetterbox; + const IntRect& box = screen->mOutputLetterbox; glViewport(box.left, box.top, box.width, box.height); shader.Bind(); @@ -115,8 +115,8 @@ static void prepareInterleavedPresent(FPresentStereoShaderBase& shader) shader.GrayFormula.Set(static_cast(gl_satformula)); } shader.Scale.Set( - GLRenderer->mScreenViewport.width / (float)GLRenderer->mBuffers->GetWidth(), - GLRenderer->mScreenViewport.height / (float)GLRenderer->mBuffers->GetHeight()); + screen->mScreenViewport.width / (float)GLRenderer->mBuffers->GetWidth(), + screen->mScreenViewport.height / (float)GLRenderer->mBuffers->GetHeight()); } // fixme: I don't know how to get absolute window position on Mac and Linux @@ -150,7 +150,7 @@ void CheckerInterleaved3D::Present() const GLRenderer->mPresent3dCheckerShader->WindowPositionParity.Set( (windowVOffset + windowHOffset - + GLRenderer->mOutputLetterbox.height + 1 // +1 because of origin at bottom + + screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom ) % 2 // because we want the top pixel offset, but gl_FragCoord.y is the bottom pixel offset ); @@ -162,15 +162,15 @@ void s3d::CheckerInterleaved3D::AdjustViewports() const // decrease the total pixel count by 2, but keep the same aspect ratio const float sqrt2 = 1.41421356237f; // Change size of renderbuffer, and align to screen - GLRenderer->mSceneViewport.height /= sqrt2; - GLRenderer->mSceneViewport.top /= sqrt2; - GLRenderer->mSceneViewport.width /= sqrt2; - GLRenderer->mSceneViewport.left /= sqrt2; + screen->mSceneViewport.height /= sqrt2; + screen->mSceneViewport.top /= sqrt2; + screen->mSceneViewport.width /= sqrt2; + screen->mSceneViewport.left /= sqrt2; - GLRenderer->mScreenViewport.height /= sqrt2; - GLRenderer->mScreenViewport.top /= sqrt2; - GLRenderer->mScreenViewport.width /= sqrt2; - GLRenderer->mScreenViewport.left /= sqrt2; + screen->mScreenViewport.height /= sqrt2; + screen->mScreenViewport.top /= sqrt2; + screen->mScreenViewport.width /= sqrt2; + screen->mScreenViewport.left /= sqrt2; } void ColumnInterleaved3D::Present() const @@ -214,7 +214,7 @@ void RowInterleaved3D::Present() const GLRenderer->mPresent3dRowShader->WindowPositionParity.Set( (windowVOffset - + GLRenderer->mOutputLetterbox.height + 1 // +1 because of origin at bottom + + screen->mOutputLetterbox.height + 1 // +1 because of origin at bottom ) % 2 ); diff --git a/src/gl/stereo3d/gl_quadstereo.cpp b/src/gl/stereo3d/gl_quadstereo.cpp index 545dded20..dce114caf 100644 --- a/src/gl/stereo3d/gl_quadstereo.cpp +++ b/src/gl/stereo3d/gl_quadstereo.cpp @@ -80,12 +80,12 @@ void QuadStereo::Present() const glDrawBuffer(GL_BACK_LEFT); GLRenderer->ClearBorders(); GLRenderer->mBuffers->BindEyeTexture(0, 0); - GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true); glDrawBuffer(GL_BACK_RIGHT); GLRenderer->ClearBorders(); GLRenderer->mBuffers->BindEyeTexture(1, 0); - GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true); glDrawBuffer(GL_BACK); } @@ -94,7 +94,7 @@ void QuadStereo::Present() const GLRenderer->mBuffers->BindOutputFB(); GLRenderer->ClearBorders(); GLRenderer->mBuffers->BindEyeTexture(0, 0); - GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true); } } diff --git a/src/gl/stereo3d/gl_sidebyside3d.cpp b/src/gl/stereo3d/gl_sidebyside3d.cpp index e6c25e99b..a8a216dd8 100644 --- a/src/gl/stereo3d/gl_sidebyside3d.cpp +++ b/src/gl/stereo3d/gl_sidebyside3d.cpp @@ -44,11 +44,11 @@ void SideBySideBase::Present() const GLRenderer->ClearBorders(); // Compute screen regions to use for left and right eye views - int leftWidth = GLRenderer->mOutputLetterbox.width / 2; - int rightWidth = GLRenderer->mOutputLetterbox.width - leftWidth; - GL_IRECT leftHalfScreen = GLRenderer->mOutputLetterbox; + int leftWidth = screen->mOutputLetterbox.width / 2; + int rightWidth = screen->mOutputLetterbox.width - leftWidth; + IntRect leftHalfScreen = screen->mOutputLetterbox; leftHalfScreen.width = leftWidth; - GL_IRECT rightHalfScreen = GLRenderer->mOutputLetterbox; + IntRect rightHalfScreen = screen->mOutputLetterbox; rightHalfScreen.width = rightWidth; rightHalfScreen.left += leftWidth; @@ -63,10 +63,10 @@ void SideBySideBase::Present() const void SideBySideBase::AdjustViewports() const { // Change size of renderbuffer, and align to screen - GLRenderer->mSceneViewport.width /= 2; - GLRenderer->mSceneViewport.left /= 2; - GLRenderer->mScreenViewport.width /= 2; - GLRenderer->mScreenViewport.left /= 2; + screen->mSceneViewport.width /= 2; + screen->mSceneViewport.left /= 2; + screen->mScreenViewport.width /= 2; + screen->mScreenViewport.left /= 2; } /* static */ @@ -101,8 +101,8 @@ SideBySideFull::SideBySideFull(double ipdMeters) void SideBySideFull::AdjustPlayerSprites() const /* override */ { // Show weapon at double width, so it would appear normal width after rescaling - int w = GLRenderer->mScreenViewport.width; - int h = GLRenderer->mScreenViewport.height; + int w = screen->mScreenViewport.width; + int h = screen->mScreenViewport.height; gl_RenderState.mProjectionMatrix.ortho(w/2, w + w/2, h, 0, -1.0f, 1.0f); gl_RenderState.ApplyMatrices(); } @@ -120,12 +120,12 @@ void TopBottom3D::Present() const GLRenderer->ClearBorders(); // Compute screen regions to use for left and right eye views - int topHeight = GLRenderer->mOutputLetterbox.height / 2; - int bottomHeight = GLRenderer->mOutputLetterbox.height - topHeight; - GL_IRECT topHalfScreen = GLRenderer->mOutputLetterbox; + int topHeight = screen->mOutputLetterbox.height / 2; + int bottomHeight = screen->mOutputLetterbox.height - topHeight; + IntRect topHalfScreen = screen->mOutputLetterbox; topHalfScreen.height = topHeight; topHalfScreen.top = topHeight; - GL_IRECT bottomHalfScreen = GLRenderer->mOutputLetterbox; + IntRect bottomHalfScreen = screen->mOutputLetterbox; bottomHalfScreen.height = bottomHeight; bottomHalfScreen.top = 0; @@ -140,10 +140,10 @@ void TopBottom3D::Present() const void TopBottom3D::AdjustViewports() const { // Change size of renderbuffer, and align to screen - GLRenderer->mSceneViewport.height /= 2; - GLRenderer->mSceneViewport.top /= 2; - GLRenderer->mScreenViewport.height /= 2; - GLRenderer->mScreenViewport.top /= 2; + screen->mSceneViewport.height /= 2; + screen->mSceneViewport.top /= 2; + screen->mScreenViewport.height /= 2; + screen->mScreenViewport.top /= 2; } } /* namespace s3d */ diff --git a/src/gl/stereo3d/gl_stereo_leftright.cpp b/src/gl/stereo3d/gl_stereo_leftright.cpp index eb58a2eaa..94633bbc0 100644 --- a/src/gl/stereo3d/gl_stereo_leftright.cpp +++ b/src/gl/stereo3d/gl_stereo_leftright.cpp @@ -93,7 +93,7 @@ void LeftEyeView::Present() const GLRenderer->mBuffers->BindOutputFB(); GLRenderer->ClearBorders(); GLRenderer->mBuffers->BindEyeTexture(0, 0); - GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true); } /* static */ @@ -109,7 +109,7 @@ void RightEyeView::Present() const GLRenderer->mBuffers->BindOutputFB(); GLRenderer->ClearBorders(); GLRenderer->mBuffers->BindEyeTexture(0, 0); - GLRenderer->DrawPresentTexture(GLRenderer->mOutputLetterbox, true); + GLRenderer->DrawPresentTexture(screen->mOutputLetterbox, true); } diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 9d555f3ee..51441fd8f 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -39,6 +39,7 @@ #include "hwrenderer/utility/hw_clock.h" #include "gl/data/gl_vertexbuffer.h" #include "gl/models/gl_models.h" +#include "gl/stereo3d/gl_stereo3d.h" #include "gl_debug.h" #include "r_videoscale.h" @@ -137,7 +138,7 @@ void OpenGLFrameBuffer::InitializeState() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLRenderer->Initialize(GetWidth(), GetHeight()); - GLRenderer->SetOutputViewport(nullptr); + SetOutputViewport(nullptr); } //========================================================================== @@ -167,7 +168,7 @@ void OpenGLFrameBuffer::Update() GLRenderer->mVBO->OutputResized(Width, Height); } - GLRenderer->SetOutputViewport(nullptr); + SetOutputViewport(nullptr); } //=========================================================================== @@ -379,6 +380,17 @@ void OpenGLFrameBuffer::ResetFixedColormap() } } +bool OpenGLFrameBuffer::RenderBuffersEnabled() +{ + return FGLRenderBuffers::IsEnabled(); +} + +void OpenGLFrameBuffer::SetOutputViewport(IntRect *bounds) +{ + Super::SetOutputViewport(bounds); + s3d::Stereo3DMode::getCurrentMode().AdjustViewports(); +} + void OpenGLFrameBuffer::UpdatePalette() { @@ -446,7 +458,7 @@ void OpenGLFrameBuffer::BeginFrame() void OpenGLFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma) { - const auto &viewport = GLRenderer->mOutputLetterbox; + const auto &viewport = mOutputLetterbox; // Grab what is in the back buffer. // We cannot rely on SCREENWIDTH/HEIGHT here because the output may have been scaled. @@ -513,10 +525,10 @@ void OpenGLFrameBuffer::GameRestart() void OpenGLFrameBuffer::ScaleCoordsFromWindow(int16_t &x, int16_t &y) { - int letterboxX = GLRenderer->mOutputLetterbox.left; - int letterboxY = GLRenderer->mOutputLetterbox.top; - int letterboxWidth = GLRenderer->mOutputLetterbox.width; - int letterboxHeight = GLRenderer->mOutputLetterbox.height; + int letterboxX = mOutputLetterbox.left; + int letterboxY = mOutputLetterbox.top; + int letterboxWidth = mOutputLetterbox.width; + int letterboxHeight = mOutputLetterbox.height; // Subtract the LB video mode letterboxing if (IsFullscreen()) diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index d2764419f..1541b3676 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -46,6 +46,8 @@ public: void TextureFilterChanged() override; void ResetFixedColormap() override; void BeginFrame() override; + bool RenderBuffersEnabled() override; + void SetOutputViewport(IntRect *bounds) override; // Retrieves a buffer containing image data for a screenshot. // Hint: Pitch can be negative for upside-down images, in which case buffer diff --git a/src/gl/system/gl_wipe.cpp b/src/gl/system/gl_wipe.cpp index bcd0183d8..3c8ca3523 100644 --- a/src/gl/system/gl_wipe.cpp +++ b/src/gl/system/gl_wipe.cpp @@ -115,7 +115,7 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type) return false; } - const auto &viewport = GLRenderer->mScreenViewport; + const auto &viewport = screen->mScreenViewport; wipestartscreen = new FHardwareTexture(true); wipestartscreen->CreateTexture(NULL, viewport.width, viewport.height, 0, false, 0, "WipeStartScreen"); GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1); @@ -163,7 +163,7 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type) void OpenGLFrameBuffer::WipeEndScreen() { GLRenderer->Flush(); - const auto &viewport = GLRenderer->mScreenViewport; + const auto &viewport = screen->mScreenViewport; wipeendscreen = new FHardwareTexture(true); wipeendscreen->CreateTexture(NULL, viewport.width, viewport.height, 0, false, 0, "WipeEndScreen"); GLRenderer->mSamplerManager->Bind(0, CLAMP_NOFILTER, -1); @@ -206,7 +206,7 @@ bool OpenGLFrameBuffer::WipeDo(int ticks) if (FGLRenderBuffers::IsEnabled()) { GLRenderer->mBuffers->BindCurrentFB(); - const auto &bounds = GLRenderer->mScreenViewport; + const auto &bounds = screen->mScreenViewport; glViewport(bounds.left, bounds.top, bounds.width, bounds.height); } diff --git a/src/v_video.cpp b/src/v_video.cpp index 0cb424d2c..b269518cc 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -75,6 +75,8 @@ EXTERN_CVAR(Bool, cl_capfps) EXTERN_CVAR(Float, vid_brightness) EXTERN_CVAR(Float, vid_contrast) +CVAR(Bool, gl_scale_viewport, true, CVAR_ARCHIVE); +EXTERN_CVAR(Int, screenblocks) CUSTOM_CVAR(Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { @@ -134,6 +136,8 @@ public: bool SetFlash(PalEntry rgb, int amount) { DBGBREAK; return false; } void GetFlash(PalEntry &rgb, int &amount) { DBGBREAK; } bool IsFullscreen() { DBGBREAK; return 0; } + int GetClientWidth() { DBGBREAK; return 0; } + int GetClientHeight() { DBGBREAK; return 0; } float Gamma; }; @@ -967,6 +971,117 @@ void DFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int width, i } +//========================================================================== +// +// Calculates the viewport values needed for 2D and 3D operations +// +//========================================================================== + +void DFrameBuffer::SetOutputViewport(IntRect *bounds) +{ + if (bounds) + { + mSceneViewport = *bounds; + mScreenViewport = *bounds; + mOutputLetterbox = *bounds; + return; + } + + // Special handling so the view with a visible status bar displays properly + int height, width; + if (screenblocks >= 10) + { + height = GetHeight(); + width = GetWidth(); + } + else + { + height = (screenblocks*GetHeight() / 10) & ~7; + width = (screenblocks*GetWidth() / 10); + } + + // Back buffer letterbox for the final output + int clientWidth = GetClientWidth(); + int clientHeight = GetClientHeight(); + if (clientWidth == 0 || clientHeight == 0) + { + // When window is minimized there may not be any client area. + // Pretend to the rest of the render code that we just have a very small window. + clientWidth = 160; + clientHeight = 120; + } + int screenWidth = GetWidth(); + int screenHeight = GetHeight(); + float scaleX, scaleY; + if (ViewportIsScaled43()) + { + scaleX = MIN(clientWidth / (float)screenWidth, clientHeight / (screenHeight * 1.2f)); + scaleY = scaleX * 1.2f; + } + else + { + scaleX = MIN(clientWidth / (float)screenWidth, clientHeight / (float)screenHeight); + scaleY = scaleX; + } + mOutputLetterbox.width = (int)round(screenWidth * scaleX); + mOutputLetterbox.height = (int)round(screenHeight * scaleY); + 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 = screenWidth; + mScreenViewport.height = screenHeight; + + // Viewport for the 3D scene + mSceneViewport.left = viewwindowx; + mSceneViewport.top = screenHeight - (height + viewwindowy - ((height - viewheight) / 2)); + mSceneViewport.width = viewwidth; + mSceneViewport.height = height; + + // Scale viewports to fit letterbox + bool notScaled = ((mScreenViewport.width == ViewportScaledWidth(mScreenViewport.width, mScreenViewport.height)) && + (mScreenViewport.width == ViewportScaledHeight(mScreenViewport.width, mScreenViewport.height)) && + !ViewportIsScaled43()); + if ((gl_scale_viewport && !IsFullscreen() && notScaled) || !RenderBuffersEnabled()) + { + mScreenViewport.width = mOutputLetterbox.width; + mScreenViewport.height = mOutputLetterbox.height; + mSceneViewport.left = (int)round(mSceneViewport.left * scaleX); + mSceneViewport.top = (int)round(mSceneViewport.top * scaleY); + mSceneViewport.width = (int)round(mSceneViewport.width * scaleX); + mSceneViewport.height = (int)round(mSceneViewport.height * scaleY); + + // Without render buffers we have to render directly to the letterbox + if (!RenderBuffersEnabled()) + { + 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 DFrameBuffer::ScreenToWindowX(int x) +{ + return mScreenViewport.left + (int)round(x * mScreenViewport.width / (float)GetWidth()); +} + +int DFrameBuffer::ScreenToWindowY(int y) +{ + return mScreenViewport.top + mScreenViewport.height - (int)round(y * mScreenViewport.height / (float)GetHeight()); +} + + + CCMD(clean) { Printf ("CleanXfac: %d\nCleanYfac: %d\n", CleanXfac, CleanYfac); diff --git a/src/v_video.h b/src/v_video.h index 3e563bdc5..ca60cc7d0 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -63,6 +63,21 @@ enum EHWCaps RFL_NO_SHADERS = 256 }; +struct IntRect +{ + int left, top; + int width, height; + + + void Offset(int xofs, int yofs) + { + left += xofs; + top += yofs; + } +}; + + + extern int CleanWidth, CleanHeight, CleanXfac, CleanYfac; @@ -332,6 +347,10 @@ public: int hwcaps = 0; int instack[2] = { 0,0 }; // this is globally maintained state for portal recursion avoidance. + IntRect mScreenViewport; + IntRect mSceneViewport; + IntRect mOutputLetterbox; + public: DFrameBuffer (int width, int height, bool bgra); virtual ~DFrameBuffer() {} @@ -385,6 +404,11 @@ public: virtual void ResetFixedColormap() {} virtual void BeginFrame() {} + virtual int GetClientWidth() = 0; + virtual int GetClientHeight() = 0; + virtual bool RenderBuffersEnabled() { return false; }; + + // Begin 2D drawing operations. // Returns true if hardware-accelerated 2D has been entered, false if not. void Begin2D(bool copy3d) { isIn2D = true; } @@ -472,6 +496,10 @@ public: // Calculate gamma table void CalcGamma(float gamma, uint8_t gammalookup[256]); + virtual void SetOutputViewport(IntRect *bounds); + int ScreenToWindowX(int x); + int ScreenToWindowY(int y); + // Retrieves a buffer containing image data for a screenshot. // Hint: Pitch can be negative for upside-down images, in which case buffer