2016-09-14 18:01:13 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Copyright(C) 2010-2016 Christoph Oelckers
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with this program. If not, see http://www.gnu.org/licenses/
|
|
|
|
//
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
//
|
2013-12-05 12:43:29 +00:00
|
|
|
/*
|
|
|
|
** gl_framebuffer.cpp
|
|
|
|
** Implementation of the non-hardware specific parts of the
|
|
|
|
** OpenGL frame buffer
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gl/system/gl_system.h"
|
|
|
|
#include "m_swap.h"
|
|
|
|
#include "v_video.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "m_png.h"
|
|
|
|
#include "m_crc32.h"
|
|
|
|
#include "vectors.h"
|
|
|
|
#include "v_palette.h"
|
|
|
|
#include "templates.h"
|
2017-03-17 20:12:09 +00:00
|
|
|
#include "textures/skyboxtexture.h"
|
2013-12-05 12:43:29 +00:00
|
|
|
|
|
|
|
#include "gl/system/gl_interface.h"
|
|
|
|
#include "gl/system/gl_framebuffer.h"
|
|
|
|
#include "gl/renderer/gl_renderer.h"
|
2018-04-03 20:50:47 +00:00
|
|
|
#include "gl/renderer/gl_renderbuffers.h"
|
2014-07-13 20:37:34 +00:00
|
|
|
#include "gl/renderer/gl_renderstate.h"
|
2013-12-05 12:43:29 +00:00
|
|
|
#include "gl/renderer/gl_lightdata.h"
|
|
|
|
#include "gl/textures/gl_hwtexture.h"
|
2018-04-08 10:11:51 +00:00
|
|
|
#include "gl/textures/gl_samplers.h"
|
2013-12-05 12:43:29 +00:00
|
|
|
#include "gl/utility/gl_clock.h"
|
2018-03-28 14:40:09 +00:00
|
|
|
#include "gl/data/gl_vertexbuffer.h"
|
2016-08-17 18:33:10 +00:00
|
|
|
#include "gl_debug.h"
|
2017-07-27 07:05:01 +00:00
|
|
|
#include "r_videoscale.h"
|
2013-12-05 12:43:29 +00:00
|
|
|
|
|
|
|
EXTERN_CVAR (Float, vid_brightness)
|
|
|
|
EXTERN_CVAR (Float, vid_contrast)
|
|
|
|
EXTERN_CVAR (Bool, vid_vsync)
|
|
|
|
|
|
|
|
CVAR(Bool, gl_aalines, false, CVAR_ARCHIVE)
|
|
|
|
|
|
|
|
FGLRenderer *GLRenderer;
|
|
|
|
|
|
|
|
void gl_LoadExtensions();
|
|
|
|
void gl_PrintStartupLog();
|
2014-05-11 11:27:51 +00:00
|
|
|
void gl_SetupMenu();
|
2013-12-05 12:43:29 +00:00
|
|
|
|
2016-07-26 19:27:02 +00:00
|
|
|
CUSTOM_CVAR(Int, vid_hwgamma, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
|
|
|
{
|
|
|
|
if (self < 0 || self > 2) self = 2;
|
|
|
|
if (GLRenderer != NULL && GLRenderer->framebuffer != NULL) GLRenderer->framebuffer->DoSetGamma();
|
|
|
|
}
|
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen) :
|
2016-10-11 13:43:12 +00:00
|
|
|
Super(hMonitor, width, height, bits, refreshHz, fullscreen, false)
|
2013-12-05 12:43:29 +00:00
|
|
|
{
|
2016-08-07 23:11:43 +00:00
|
|
|
// SetVSync needs to be at the very top to workaround a bug in Nvidia's OpenGL driver.
|
|
|
|
// If wglSwapIntervalEXT is called after glBindFramebuffer in a frame the setting is not changed!
|
2017-03-03 15:30:04 +00:00
|
|
|
Super::SetVSync(vid_vsync);
|
2016-08-07 23:11:43 +00:00
|
|
|
|
2016-08-25 23:36:21 +00:00
|
|
|
// Make sure all global variables tracking OpenGL context state are reset..
|
|
|
|
FHardwareTexture::InitGlobalState();
|
|
|
|
FMaterial::InitGlobalState();
|
|
|
|
gl_RenderState.Reset();
|
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
GLRenderer = new FGLRenderer(this);
|
|
|
|
memcpy (SourcePalette, GPalette.BaseColors, sizeof(PalEntry)*256);
|
|
|
|
UpdatePalette ();
|
|
|
|
ScreenshotBuffer = NULL;
|
|
|
|
|
|
|
|
InitializeState();
|
2016-08-17 18:33:10 +00:00
|
|
|
mDebug = std::make_shared<FGLDebug>();
|
|
|
|
mDebug->Update();
|
2013-12-05 12:43:29 +00:00
|
|
|
gl_SetupMenu();
|
|
|
|
DoSetGamma();
|
|
|
|
}
|
|
|
|
|
|
|
|
OpenGLFrameBuffer::~OpenGLFrameBuffer()
|
|
|
|
{
|
|
|
|
delete GLRenderer;
|
|
|
|
GLRenderer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Initializes the GL renderer
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::InitializeState()
|
|
|
|
{
|
|
|
|
static bool first=true;
|
|
|
|
|
2014-04-06 12:35:44 +00:00
|
|
|
if (first)
|
|
|
|
{
|
2017-04-14 13:32:04 +00:00
|
|
|
if (ogl_LoadFunctions() == ogl_LOAD_FAILED)
|
|
|
|
{
|
|
|
|
I_FatalError("Failed to load OpenGL functions.");
|
|
|
|
}
|
2014-04-06 12:35:44 +00:00
|
|
|
}
|
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
gl_LoadExtensions();
|
|
|
|
Super::InitializeState();
|
2014-09-14 19:42:14 +00:00
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
if (first)
|
|
|
|
{
|
|
|
|
first=false;
|
|
|
|
gl_PrintStartupLog();
|
|
|
|
}
|
2016-04-30 13:28:35 +00:00
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
glClearDepth(1.0f);
|
|
|
|
glDepthFunc(GL_LESS);
|
|
|
|
|
|
|
|
glEnable(GL_DITHER);
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
glEnable(GL_POLYGON_OFFSET_LINE);
|
|
|
|
glEnable(GL_BLEND);
|
2014-07-14 16:48:46 +00:00
|
|
|
glEnable(GL_DEPTH_CLAMP);
|
2013-12-05 12:43:29 +00:00
|
|
|
glDisable(GL_DEPTH_TEST);
|
2016-09-01 09:52:52 +00:00
|
|
|
if (gl.legacyMode) glEnable(GL_TEXTURE_2D);
|
2013-12-05 12:43:29 +00:00
|
|
|
glDisable(GL_LINE_SMOOTH);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
2016-08-08 12:24:48 +00:00
|
|
|
GLRenderer->Initialize(GetWidth(), GetHeight());
|
2016-07-26 19:27:02 +00:00
|
|
|
GLRenderer->SetOutputViewport(nullptr);
|
|
|
|
Begin2D(false);
|
2013-12-05 12:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Updates the screen
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::Update()
|
|
|
|
{
|
|
|
|
if (!CanUpdate())
|
|
|
|
{
|
|
|
|
GLRenderer->Flush();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Begin2D(false);
|
|
|
|
|
|
|
|
DrawRateStuff();
|
|
|
|
GLRenderer->Flush();
|
|
|
|
|
2016-08-29 22:33:02 +00:00
|
|
|
Swap();
|
2013-12-05 12:43:29 +00:00
|
|
|
CheckBench();
|
2016-09-12 18:43:45 +00:00
|
|
|
|
2017-10-08 00:18:37 +00:00
|
|
|
int initialWidth = IsFullscreen() ? VideoWidth : GetClientWidth();
|
|
|
|
int initialHeight = IsFullscreen() ? VideoHeight : GetClientHeight();
|
|
|
|
int clientWidth = ViewportScaledWidth(initialWidth, initialHeight);
|
|
|
|
int clientHeight = ViewportScaledHeight(initialWidth, initialHeight);
|
2017-02-09 01:56:00 +00:00
|
|
|
if (clientWidth > 0 && clientHeight > 0 && (Width != clientWidth || Height != clientHeight))
|
2016-09-12 18:43:45 +00:00
|
|
|
{
|
2017-02-09 01:56:00 +00:00
|
|
|
// Do not call Resize here because it's only for software canvases
|
2018-03-27 12:14:46 +00:00
|
|
|
Width = clientWidth;
|
2017-02-09 01:56:00 +00:00
|
|
|
Height = clientHeight;
|
|
|
|
V_OutputResized(Width, Height);
|
|
|
|
GLRenderer->mVBO->OutputResized(Width, Height);
|
2016-09-12 18:43:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GLRenderer->SetOutputViewport(nullptr);
|
2013-12-05 12:43:29 +00:00
|
|
|
}
|
|
|
|
|
2018-04-03 22:21:25 +00:00
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV)
|
|
|
|
{
|
2018-04-07 21:30:28 +00:00
|
|
|
if (!V_IsHardwareRenderer())
|
|
|
|
{
|
2018-04-03 22:21:25 +00:00
|
|
|
Super::RenderTextureView(tex, Viewpoint, FOV);
|
2018-04-07 21:30:28 +00:00
|
|
|
}
|
2018-04-03 22:21:25 +00:00
|
|
|
else if (GLRenderer != nullptr)
|
|
|
|
{
|
|
|
|
GLRenderer->RenderTextureView(tex, Viewpoint, FOV);
|
|
|
|
camtexcount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Render the view to a savegame picture
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int width, int height)
|
|
|
|
{
|
2018-04-07 21:30:28 +00:00
|
|
|
if (!V_IsHardwareRenderer())
|
2018-04-05 21:08:09 +00:00
|
|
|
Super::WriteSavePic(player, file, width, height);
|
|
|
|
|
2018-04-03 22:21:25 +00:00
|
|
|
if (GLRenderer != nullptr)
|
|
|
|
GLRenderer->WriteSavePic(player, file, width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::RenderView(player_t *player)
|
|
|
|
{
|
|
|
|
if (GLRenderer != nullptr)
|
|
|
|
GLRenderer->RenderView(player);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-04-03 20:50:47 +00:00
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
EXTERN_CVAR(Bool, r_drawvoxels)
|
|
|
|
EXTERN_CVAR(Int, gl_tonemap)
|
|
|
|
|
|
|
|
uint32_t OpenGLFrameBuffer::GetCaps()
|
|
|
|
{
|
2018-04-07 21:30:28 +00:00
|
|
|
if (!V_IsHardwareRenderer())
|
|
|
|
return Super::GetCaps();
|
2018-04-03 20:50:47 +00:00
|
|
|
|
|
|
|
// describe our basic feature set
|
|
|
|
ActorRenderFeatureFlags FlagSet = RFF_FLATSPRITES | RFF_MODELS | RFF_SLOPE3DFLOORS |
|
|
|
|
RFF_TILTPITCH | RFF_ROLLSPRITES | RFF_POLYGONAL;
|
|
|
|
if (r_drawvoxels)
|
|
|
|
FlagSet |= RFF_VOXELS;
|
|
|
|
if (gl.legacyMode)
|
|
|
|
{
|
|
|
|
// legacy mode always has truecolor because palette tonemap is not available
|
|
|
|
FlagSet |= RFF_TRUECOLOR;
|
|
|
|
}
|
|
|
|
else if (!(FGLRenderBuffers::IsEnabled()))
|
|
|
|
{
|
|
|
|
// truecolor is always available when renderbuffers are unavailable because palette tonemap is not possible
|
|
|
|
FlagSet |= RFF_TRUECOLOR | RFF_MATSHADER | RFF_BRIGHTMAP;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (gl_tonemap != 5) // not running palette tonemap shader
|
|
|
|
FlagSet |= RFF_TRUECOLOR;
|
|
|
|
FlagSet |= RFF_MATSHADER | RFF_POSTSHADER | RFF_BRIGHTMAP;
|
|
|
|
}
|
|
|
|
return (uint32_t)FlagSet;
|
|
|
|
}
|
2013-12-05 12:43:29 +00:00
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Swap the buffers
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2016-12-25 21:56:18 +00:00
|
|
|
CVAR(Bool, gl_finishbeforeswap, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
2016-12-03 19:09:25 +00:00
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
void OpenGLFrameBuffer::Swap()
|
|
|
|
{
|
2016-12-25 21:56:18 +00:00
|
|
|
bool swapbefore = gl_finishbeforeswap && camtexcount == 0;
|
2013-12-05 12:43:29 +00:00
|
|
|
Finish.Reset();
|
|
|
|
Finish.Clock();
|
2016-12-25 21:56:18 +00:00
|
|
|
if (swapbefore) glFinish();
|
2013-12-05 12:43:29 +00:00
|
|
|
SwapBuffers();
|
2016-12-25 21:56:18 +00:00
|
|
|
if (!swapbefore) glFinish();
|
2013-12-05 12:43:29 +00:00
|
|
|
Finish.Unclock();
|
2016-12-25 21:56:18 +00:00
|
|
|
camtexcount = 0;
|
2013-12-05 12:43:29 +00:00
|
|
|
FHardwareTexture::UnbindAll();
|
2016-08-17 18:33:10 +00:00
|
|
|
mDebug->Update();
|
2013-12-05 12:43:29 +00:00
|
|
|
}
|
|
|
|
|
2017-03-03 15:30:04 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Enable/disable vertical sync
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::SetVSync(bool vsync)
|
|
|
|
{
|
|
|
|
// Switch to the default frame buffer because some drivers associate the vsync state with the bound FB object.
|
|
|
|
GLint oldDrawFramebufferBinding = 0, oldReadFramebufferBinding = 0;
|
|
|
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldDrawFramebufferBinding);
|
|
|
|
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &oldReadFramebufferBinding);
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
|
|
|
|
|
|
|
Super::SetVSync(vsync);
|
|
|
|
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oldDrawFramebufferBinding);
|
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, oldReadFramebufferBinding);
|
|
|
|
}
|
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// DoSetGamma
|
|
|
|
//
|
|
|
|
// (Unfortunately Windows has some safety precautions that block gamma ramps
|
|
|
|
// that are considered too extreme. As a result this doesn't work flawlessly)
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::DoSetGamma()
|
|
|
|
{
|
2016-07-26 19:27:02 +00:00
|
|
|
bool useHWGamma = m_supportsGamma && ((vid_hwgamma == 0) || (vid_hwgamma == 2 && IsFullscreen()));
|
|
|
|
if (useHWGamma)
|
2013-12-05 12:43:29 +00:00
|
|
|
{
|
2017-03-08 17:50:37 +00:00
|
|
|
uint16_t gammaTable[768];
|
2016-07-26 19:27:02 +00:00
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
// This formula is taken from Doomsday
|
|
|
|
float gamma = clamp<float>(Gamma, 0.1f, 4.f);
|
|
|
|
float contrast = clamp<float>(vid_contrast, 0.1f, 3.f);
|
|
|
|
float bright = clamp<float>(vid_brightness, -0.8f, 0.8f);
|
|
|
|
|
|
|
|
double invgamma = 1 / gamma;
|
|
|
|
double norm = pow(255., invgamma - 1);
|
|
|
|
|
|
|
|
for (int i = 0; i < 256; i++)
|
|
|
|
{
|
|
|
|
double val = i * contrast - (contrast - 1) * 127;
|
|
|
|
val += bright * 128;
|
2016-09-21 19:08:53 +00:00
|
|
|
if(gamma != 1) val = pow(val, invgamma) / norm;
|
2013-12-05 12:43:29 +00:00
|
|
|
|
2017-03-08 17:50:37 +00:00
|
|
|
gammaTable[i] = gammaTable[i + 256] = gammaTable[i + 512] = (uint16_t)clamp<double>(val*256, 0, 0xffff);
|
2013-12-05 12:43:29 +00:00
|
|
|
}
|
|
|
|
SetGammaTable(gammaTable);
|
2016-07-26 19:27:02 +00:00
|
|
|
|
|
|
|
HWGammaActive = true;
|
|
|
|
}
|
|
|
|
else if (HWGammaActive)
|
|
|
|
{
|
|
|
|
ResetGammaTable();
|
|
|
|
HWGammaActive = false;
|
2013-12-05 12:43:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLFrameBuffer::SetGamma(float gamma)
|
|
|
|
{
|
|
|
|
DoSetGamma();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLFrameBuffer::SetBrightness(float bright)
|
|
|
|
{
|
|
|
|
DoSetGamma();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLFrameBuffer::SetContrast(float contrast)
|
|
|
|
{
|
|
|
|
DoSetGamma();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
2018-04-08 06:03:46 +00:00
|
|
|
void OpenGLFrameBuffer::CleanForRestart()
|
|
|
|
{
|
|
|
|
if (GLRenderer)
|
|
|
|
GLRenderer->ResetSWScene();
|
|
|
|
}
|
|
|
|
|
2018-04-08 10:11:51 +00:00
|
|
|
void OpenGLFrameBuffer::SetTextureFilterMode()
|
|
|
|
{
|
|
|
|
if (GLRenderer != nullptr && GLRenderer->mSamplerManager != nullptr) GLRenderer->mSamplerManager->SetTextureFilterMode();
|
|
|
|
}
|
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
void OpenGLFrameBuffer::UpdatePalette()
|
|
|
|
{
|
2016-08-25 17:58:50 +00:00
|
|
|
if (GLRenderer)
|
|
|
|
GLRenderer->ClearTonemapPalette();
|
2013-12-05 12:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::GetFlashedPalette (PalEntry pal[256])
|
|
|
|
{
|
|
|
|
memcpy(pal, SourcePalette, 256*sizeof(PalEntry));
|
|
|
|
}
|
|
|
|
|
|
|
|
PalEntry *OpenGLFrameBuffer::GetPalette ()
|
|
|
|
{
|
|
|
|
return SourcePalette;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenGLFrameBuffer::SetFlash(PalEntry rgb, int amount)
|
|
|
|
{
|
|
|
|
Flash = PalEntry(amount, rgb.r, rgb.g, rgb.b);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::GetFlash(PalEntry &rgb, int &amount)
|
|
|
|
{
|
|
|
|
rgb = Flash;
|
|
|
|
rgb.a = 0;
|
|
|
|
amount = Flash.a;
|
|
|
|
}
|
|
|
|
|
2018-04-03 20:50:47 +00:00
|
|
|
void OpenGLFrameBuffer::InitForLevel()
|
|
|
|
{
|
|
|
|
if (GLRenderer != NULL)
|
|
|
|
{
|
|
|
|
GLRenderer->SetupLevel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::SetClearColor(int color)
|
|
|
|
{
|
|
|
|
PalEntry pe = GPalette.BaseColors[color];
|
|
|
|
GLRenderer->mSceneClearColor[0] = pe.r / 255.f;
|
|
|
|
GLRenderer->mSceneClearColor[1] = pe.g / 255.f;
|
|
|
|
GLRenderer->mSceneClearColor[2] = pe.b / 255.f;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
2017-04-01 10:59:58 +00:00
|
|
|
bool OpenGLFrameBuffer::Begin2D(bool copy3d)
|
2013-12-05 12:43:29 +00:00
|
|
|
{
|
2017-04-01 10:59:58 +00:00
|
|
|
Super::Begin2D(copy3d);
|
2017-03-28 11:06:24 +00:00
|
|
|
ClearClipRect();
|
2014-07-13 20:37:34 +00:00
|
|
|
gl_RenderState.mViewMatrix.loadIdentity();
|
|
|
|
gl_RenderState.mProjectionMatrix.ortho(0, GetWidth(), GetHeight(), 0, -1.0f, 1.0f);
|
|
|
|
gl_RenderState.ApplyMatrices();
|
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
|
|
|
|
// Korshun: ENABLE AUTOMAP ANTIALIASING!!!
|
|
|
|
if (gl_aalines)
|
|
|
|
glEnable(GL_LINE_SMOOTH);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glDisable(GL_MULTISAMPLE);
|
|
|
|
glDisable(GL_LINE_SMOOTH);
|
|
|
|
glLineWidth(1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GLRenderer != NULL)
|
|
|
|
GLRenderer->Begin2D();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Takes a screenshot
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
2017-12-06 08:59:20 +00:00
|
|
|
void OpenGLFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma)
|
2013-12-05 12:43:29 +00:00
|
|
|
{
|
2016-08-12 05:34:05 +00:00
|
|
|
const auto &viewport = GLRenderer->mOutputLetterbox;
|
2016-08-12 05:28:29 +00:00
|
|
|
|
|
|
|
// 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;
|
2016-08-12 05:42:49 +00:00
|
|
|
pixels.Resize(viewport.width * viewport.height * 3);
|
2016-08-12 05:28:29 +00:00
|
|
|
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:
|
2013-12-05 12:43:29 +00:00
|
|
|
int w = SCREENWIDTH;
|
|
|
|
int h = SCREENHEIGHT;
|
|
|
|
|
|
|
|
ReleaseScreenshotBuffer();
|
2017-03-09 18:54:41 +00:00
|
|
|
ScreenshotBuffer = new uint8_t[w * h * 3];
|
2013-12-05 12:43:29 +00:00
|
|
|
|
2016-08-12 05:42:49 +00:00
|
|
|
float rcpWidth = 1.0f / w;
|
|
|
|
float rcpHeight = 1.0f / h;
|
2016-08-12 05:28:29 +00:00
|
|
|
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;
|
2016-08-12 05:42:49 +00:00
|
|
|
int sindex = (sx + sy * viewport.width) * 3;
|
2016-08-12 05:28:29 +00:00
|
|
|
int dindex = (x + y * w) * 3;
|
|
|
|
ScreenshotBuffer[dindex] = pixels[sindex];
|
|
|
|
ScreenshotBuffer[dindex + 1] = pixels[sindex + 1];
|
|
|
|
ScreenshotBuffer[dindex + 2] = pixels[sindex + 2];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-05 12:43:29 +00:00
|
|
|
pitch = -w*3;
|
|
|
|
color_type = SS_RGB;
|
|
|
|
buffer = ScreenshotBuffer + w * 3 * (h - 1);
|
2017-12-06 08:59:20 +00:00
|
|
|
|
|
|
|
// Screenshot should not use gamma correction if it was already applied to rendered image
|
|
|
|
EXTERN_CVAR(Bool, fullscreen);
|
|
|
|
gamma = 1 == vid_hwgamma || (2 == vid_hwgamma && !fullscreen) ? 1.0f : Gamma;
|
2013-12-05 12:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Releases the screenshot buffer.
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::ReleaseScreenshotBuffer()
|
|
|
|
{
|
|
|
|
if (ScreenshotBuffer != NULL) delete [] ScreenshotBuffer;
|
|
|
|
ScreenshotBuffer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::GameRestart()
|
|
|
|
{
|
|
|
|
memcpy (SourcePalette, GPalette.BaseColors, sizeof(PalEntry)*256);
|
|
|
|
UpdatePalette ();
|
|
|
|
ScreenshotBuffer = NULL;
|
2018-02-15 17:40:23 +00:00
|
|
|
GLRenderer->GetSpecialTextures();
|
2014-08-21 09:02:46 +00:00
|
|
|
}
|
|
|
|
|
2017-07-29 17:26:53 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
// Subtract the LB video mode letterboxing
|
|
|
|
if (IsFullscreen())
|
|
|
|
y -= (GetTrueHeight() - VideoHeight) / 2;
|
|
|
|
|
|
|
|
x = int16_t((x - letterboxX) * Width / letterboxWidth);
|
|
|
|
y = int16_t((y - letterboxY) * Height / letterboxHeight);
|
|
|
|
}
|
2018-03-28 19:38:00 +00:00
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// 2D drawing
|
|
|
|
//
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void OpenGLFrameBuffer::Draw2D()
|
|
|
|
{
|
|
|
|
if (GLRenderer != nullptr) GLRenderer->Draw2D(&m2DDrawer);
|
|
|
|
}
|