diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ca94f1b95..b4bb035af 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -216,6 +216,8 @@ set(SRB2_CONFIG_HWRENDER ON CACHE BOOL "Enable hardware rendering through OpenGL.") set(SRB2_CONFIG_STATIC_OPENGL OFF CACHE BOOL "Use statically linked OpenGL. NOT RECOMMENDED.") +set(SRB2_CONFIG_USE_FBO_OGL ON CACHE BOOL + "Enable OpenGL FBO Downsampling support.") ### use internal libraries? if(${CMAKE_SYSTEM} MATCHES "Windows") ###set on Windows only @@ -510,6 +512,12 @@ if(${SRB2_CONFIG_HWRENDER} AND ${SRB2_CONFIG_STATIC_OPENGL}) endif() endif() +if(${SRB2_CONFIG_HWRENDER}) + if(${SRB2_CONFIG_USE_FBO_OGL}) + set(SRB2_USE_FBO_OGL ON) + add_definitions(-DUSE_FBO_OGL) + endif() +endif() # Targets diff --git a/src/Makefile b/src/Makefile index bc4eb6f3d..af8dd67b0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -199,6 +199,10 @@ ifndef NOOPENMPT HAVE_OPENMPT=1 endif +ifndef NOSCREENFBO +USE_FBO_OGL=1 +endif + ifdef MINGW include win32/Makefile.cfg endif #ifdef MINGW @@ -372,6 +376,12 @@ ifdef STATIC LIBS:=-static $(LIBS) endif +ifndef NOHW +ifdef USE_FBO_OGL +OPTS+=-DUSE_FBO_OGL +endif +endif + ifdef HAVE_MINIUPNPC ifdef NONET HAVE_MINIUPNPC='' diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index b49c0f316..b55c10bb9 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -287,6 +287,9 @@ typedef struct FSurfaceInfo FSurfaceInfo; enum hwdsetspecialstate { +#ifdef USE_FBO_OGL + HWD_SET_FRAMEBUFFER, +#endif HWD_SET_SHADERS, HWD_SET_TEXTUREFILTERMODE, diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index f373706ab..53f0e8786 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -69,6 +69,9 @@ static boolean gr_palette_rendering_state = false; // Commands and console variables // ========================================================================== +#ifdef USE_FBO_OGL +static void CV_grframebuffer_OnChange(void); +#endif static void CV_filtermode_ONChange(void); static void CV_anisotropic_ONChange(void); static void CV_screentextures_ONChange(void); @@ -96,6 +99,10 @@ consvar_t cv_grsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL, consvar_t cv_grbatching = {"gr_batching", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +#ifdef USE_FBO_OGL +consvar_t cv_grframebuffer = {"gr_framebuffer", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, CV_grframebuffer_OnChange, 0, NULL, NULL, 0, 0, NULL}; +#endif + consvar_t cv_grfofcut = {"gr_fofcut", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_fofzfightfix = {"fofzfightfix", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -210,6 +217,16 @@ static void CV_grpalettedepth_OnChange(void) HWR_SetPalette(pLocalPalette); } +#ifdef USE_FBO_OGL +static void CV_grframebuffer_OnChange(void) +{ + ONLY_IF_GL_LOADED + HWD.pfnSetSpecialState(HWD_SET_FRAMEBUFFER, cv_grframebuffer.value); + I_DownSample(); + RefreshOGLSDLSurface(); +} +#endif + // // Sets the shader state. // @@ -5965,6 +5982,9 @@ void HWR_TogglePaletteRendering(void) //added by Hurdler: console varibale that are saved void HWR_AddCommands(void) { +#ifdef USE_FBO_OGL + CV_RegisterVar(&cv_grframebuffer); +#endif CV_RegisterVar(&cv_grfiltermode); CV_RegisterVar(&cv_granisotropicmode); CV_RegisterVar(&cv_grsolvetjoin); @@ -6028,6 +6048,10 @@ void HWR_Startup(void) HWR_TogglePaletteRendering(); +#ifdef USE_FBO_OGL + HWD.pfnSetSpecialState(HWD_SET_FRAMEBUFFER, cv_grframebuffer.value); +#endif + if (msaa) { if (a2c) diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index ec5420f2c..1c51e2981 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -152,6 +152,9 @@ void HWR_SetShaderState(void); // Console variables extern consvar_t cv_grshaders; +#ifdef USE_FBO_OGL +extern consvar_t cv_grframebuffer; +#endif extern consvar_t cv_grfofcut; extern consvar_t cv_fofzfightfix; extern consvar_t cv_splitwallfix; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 8d98f190b..0ea12a793 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -119,6 +119,14 @@ static GLfloat modelMatrix[16]; GLfloat projMatrix[16]; static GLint viewport[4]; +#ifdef USE_FBO_OGL +static boolean GLFramebuffer_IsFuncAvailible(void); + +GLuint FramebufferObject, FramebufferTexture, RenderbufferObject; +GLboolean FrameBufferEnabled = GL_FALSE, RenderToFramebuffer = GL_FALSE; + +boolean supportFBO = false; +#endif // Sryder: NextTexAvail is broken for these because palette changes or changes to the texture filter or antialiasing // flush all of the stored textures, leaving them unavailable at times such as between levels @@ -428,7 +436,32 @@ typedef void (APIENTRY * PFNglCopyTexImage2D) (GLenum target, GLint level, GLenu static PFNglCopyTexImage2D pglCopyTexImage2D; typedef void (APIENTRY * PFNglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); static PFNglCopyTexSubImage2D pglCopyTexSubImage2D; -#endif + +#ifdef USE_FBO_OGL +/* 3.0 functions for framebuffers and renderbuffers */ +typedef void (APIENTRY * PFNglGenFramebuffers) (GLsizei n, GLuint *ids); +static PFNglGenFramebuffers pglGenFramebuffers; +typedef void (APIENTRY * PFNglBindFramebuffer) (GLenum target, GLuint framebuffer); +static PFNglBindFramebuffer pglBindFramebuffer; +typedef void (APIENTRY * PFNglDeleteFramebuffers) (GLsizei n, GLuint *ids); +static PFNglDeleteFramebuffers pglDeleteFramebuffers; +typedef void (APIENTRY * PFNglFramebufferTexture2D) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +static PFNglFramebufferTexture2D pglFramebufferTexture2D; +typedef GLenum (APIENTRY * PFNglCheckFramebufferStatus) (GLenum target); +static PFNglCheckFramebufferStatus pglCheckFramebufferStatus; +typedef void (APIENTRY * PFNglGenRenderbuffers) (GLsizei n, GLuint *renderbuffers); +static PFNglGenRenderbuffers pglGenRenderbuffers; +typedef void (APIENTRY * PFNglBindRenderbuffer) (GLenum target, GLuint renderbuffer); +static PFNglBindRenderbuffer pglBindRenderbuffer; +typedef void (APIENTRY * PFNglDeleteRenderbuffers) (GLsizei n, GLuint *renderbuffers); +static PFNglDeleteRenderbuffers pglDeleteRenderbuffers; +typedef void (APIENTRY * PFNglRenderbufferStorage) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +static PFNglRenderbufferStorage pglRenderbufferStorage; +typedef void (APIENTRY * PFNglFramebufferRenderbuffer) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLenum renderbuffer); +static PFNglFramebufferRenderbuffer pglFramebufferRenderbuffer; +#endif // USE_FBO_OGL + +#endif //!STATIC_OPENGL /* 1.2 functions for 3D textures */ typedef void (APIENTRY * PFNglTexImage3D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); @@ -712,8 +745,39 @@ void SetupGLFunc4(void) pglUniform2fv = GetGLFunc("glUniform2fv"); pglUniform3fv = GetGLFunc("glUniform3fv"); pglGetUniformLocation = GetGLFunc("glGetUniformLocation"); + +#ifdef USE_FBO_OGL + if (GLFramebuffer_IsFuncAvailible()) + { + pglGenFramebuffers = GetGLFunc("glGenFramebuffers"); + pglBindFramebuffer = GetGLFunc("glBindFramebuffer"); + pglDeleteFramebuffers = GetGLFunc("glDeleteFramebuffers"); + pglFramebufferTexture2D = GetGLFunc("glFramebufferTexture2D"); + pglCheckFramebufferStatus = GetGLFunc("glCheckFramebufferStatus"); + pglGenRenderbuffers = GetGLFunc("glGenRenderbuffers"); + pglBindRenderbuffer = GetGLFunc("glBindRenderbuffer"); + pglDeleteRenderbuffers = GetGLFunc("glDeleteRenderbuffers"); + pglRenderbufferStorage = GetGLFunc("glRenderbufferStorage"); + pglFramebufferRenderbuffer = GetGLFunc("glFramebufferRenderbuffer"); + } +#endif } +#ifdef USE_FBO_OGL +static boolean GLFramebuffer_IsFuncAvailible(void) +{ + //this stuff needs atleast OGL 3.0 + if (majorGL < 3) + return false; + + return((isExtAvailable("GL_ARB_framebuffer_no_attachments",gl_extensions)) && + (isExtAvailable("GL_ARB_framebuffer_object",gl_extensions)) && + (isExtAvailable("GL_ARB_framebuffer_sRGB",gl_extensions))); + + return false; +} +#endif + EXPORT boolean HWRAPI(InitShaders) (void) { if (!pglUseProgram) @@ -889,13 +953,6 @@ void SetModelView(GLint w, GLint h) { //GL_DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); - // The screen textures need to be flushed if the width or height change so that they be remade for the correct size - if (screen_width != w || screen_height != h) - FlushScreenTextures(); - - screen_width = w; - screen_height = h; - pglViewport(0, 0, w, h); pglMatrixMode(GL_PROJECTION); @@ -980,6 +1037,117 @@ EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *pTexInfo) pTexInfo->downloaded = 0; } +#ifdef USE_FBO_OGL +void GLFramebuffer_Generate(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + // Generate the framebuffer + if (FramebufferObject == 0) + pglGenFramebuffers(1, &FramebufferObject); + + if (pglCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) + GLFramebuffer_GenerateAttachments(); +} + +void GLFramebuffer_Delete(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + // Unbind the framebuffer + pglBindFramebuffer(GL_FRAMEBUFFER, 0); + + if (FramebufferObject) + pglDeleteFramebuffers(1, &FramebufferObject); + + GLFramebuffer_DeleteAttachments(); + FramebufferObject = 0; +} + +void GLFramebuffer_GenerateAttachments(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + // Bind the framebuffer + pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject); + + // Generate the framebuffer texture + if (FramebufferTexture == 0) + { + pglGenTextures(1, &FramebufferTexture); + pglBindTexture(GL_TEXTURE_2D, FramebufferTexture); + pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screen_width, screen_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + pglBindTexture(GL_TEXTURE_2D, 0); + + // Attach the framebuffer texture to the framebuffer + pglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FramebufferTexture, 0); + } + + // Generate the renderbuffer + if (RenderbufferObject == 0) + { + pglGenRenderbuffers(1, &RenderbufferObject); + + pglBindRenderbuffer(GL_RENDERBUFFER, RenderbufferObject); + pglRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, screen_width, screen_height); + pglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RenderbufferObject); + + // Clear the renderbuffer + ClearBuffer(true, true, true, NULL); + + pglBindRenderbuffer(GL_RENDERBUFFER, 0); + } + + // Unbind the framebuffer + pglBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void GLFramebuffer_DeleteAttachments(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + // Unbind the framebuffer + pglBindFramebuffer(GL_FRAMEBUFFER, 0); + + if (FramebufferTexture) + pglDeleteTextures(1, &FramebufferTexture); + + if (RenderbufferObject) + pglDeleteRenderbuffers(1, &RenderbufferObject); + + FramebufferTexture = 0; + RenderbufferObject = 0; +} + +void GLFramebuffer_Enable(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + if (FramebufferObject == 0) + GLFramebuffer_Generate(); + else if (FramebufferTexture == 0 || RenderbufferObject == 0) + GLFramebuffer_GenerateAttachments(); + + pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject); + pglBindRenderbuffer(GL_RENDERBUFFER, RenderbufferObject); +} + +void GLFramebuffer_Disable(void) +{ + if (!GLFramebuffer_IsFuncAvailible()) + return; + + pglBindFramebuffer(GL_FRAMEBUFFER, 0); + pglBindRenderbuffer(GL_RENDERBUFFER, 0); +} +#endif // -----------------+ // Flush : flush OpenGL textures @@ -2156,7 +2324,18 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) case HWD_SET_SHADERS: gl_allowshaders = Value; break; +#ifdef USE_FBO_OGL + case HWD_SET_FRAMEBUFFER: + FrameBufferEnabled = Value ? GL_TRUE : GL_FALSE; + supportFBO = GLFramebuffer_IsFuncAvailible(); + if (!supportFBO) + { + FrameBufferEnabled = GL_FALSE; + CV_Set(&cv_grframebuffer, "Off"); + } + break; +#endif case HWD_SET_TEXTUREFILTERMODE: switch (Value) { diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index c67c69303..255969d5a 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -104,6 +104,21 @@ static PFNglEnableClientState pglEnableClientState; #endif #endif +#ifdef USE_FBO_OGL +void GLFramebuffer_Generate(void); +void GLFramebuffer_Delete(void); + +void GLFramebuffer_GenerateAttachments(void); +void GLFramebuffer_DeleteAttachments(void); + +void GLFramebuffer_Enable(void); +void GLFramebuffer_Disable(void); + +extern GLuint FramebufferObject, FramebufferTexture, RenderbufferObject; +extern GLboolean FrameBufferEnabled, RenderToFramebuffer; +extern boolean supportFBO; +#endif + // ========================================================================== // GLOBAL // ========================================================================== diff --git a/src/i_video.h b/src/i_video.h index 830583822..708fde03c 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -139,4 +139,10 @@ UINT32 I_GetRefreshRate(void); boolean I_UseNativeKeyboard(void); +#ifdef USE_FBO_OGL +void RefreshOGLSDLSurface(void); +void I_DownSample(void); +extern boolean downsample; +#endif + #endif diff --git a/src/m_menu.c b/src/m_menu.c index f4ce5cf38..5c25b209d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -58,6 +58,7 @@ #ifdef HWRENDER #include "hardware/hw_main.h" +#include "hardware/r_opengl/r_opengl.h" #endif #include "d_net.h" @@ -1458,19 +1459,22 @@ static menuitem_t OP_ExpOptionsMenu[] = {IT_STRING | IT_CVAR, NULL, "Skyboxes", &cv_skybox, 70}, - {IT_STRING | IT_CVAR, NULL, "Clipping R_PointToAngle Version", &cv_pointoangleexor64, 85}, + {IT_STRING | IT_CVAR, NULL, "Clipping R_PointToAngle Version", &cv_pointoangleexor64, 90}, - {IT_STRING | IT_CVAR, NULL, "FFloorclip", &cv_ffloorclip, 95}, - {IT_STRING | IT_CVAR, NULL, "Spriteclip", &cv_spriteclip, 105}, + {IT_STRING | IT_CVAR, NULL, "FFloorclip", &cv_ffloorclip, 105}, + {IT_STRING | IT_CVAR, NULL, "Spriteclip", &cv_spriteclip, 115}, #ifdef HWRENDER - {IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_grscreentextures, 95}, + {IT_STRING | IT_CVAR, NULL, "Screen Textures", &cv_grscreentextures, 105}, +#ifdef USE_FBO_OGL + {IT_STRING | IT_CVAR, NULL, "FBO Downsampling support", &cv_grframebuffer, 115}, +#endif - {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_grpalettedepth, 105}, + {IT_STRING | IT_CVAR, NULL, "Palette Depth", &cv_grpalettedepth, 135}, - {IT_STRING | IT_CVAR, NULL, "Splitwall/Slope texture fix", &cv_splitwallfix, 125}, - {IT_STRING | IT_CVAR, NULL, "Slope midtexture peg fix", &cv_slopepegfix, 135}, - {IT_STRING | IT_CVAR, NULL, "ZFighting fix for fofs", &cv_fofzfightfix, 145}, - {IT_STRING | IT_CVAR, NULL, "FOF wall cutoff for slopes", &cv_grfofcut, 155}, + {IT_STRING | IT_CVAR, NULL, "Splitwall/Slope texture fix", &cv_splitwallfix, 155}, + {IT_STRING | IT_CVAR, NULL, "Slope midtexture peg fix", &cv_slopepegfix, 165}, + {IT_STRING | IT_CVAR, NULL, "ZFighting fix for fofs", &cv_fofzfightfix, 175}, + {IT_STRING | IT_CVAR, NULL, "FOF wall cutoff for slopes", &cv_grfofcut, 185}, #endif }; @@ -1487,6 +1491,9 @@ static const char* OP_ExpTooltips[] = "Hides Sprites which are not visible\npotentially resulting in a performance boost.", #ifdef HWRENDER "Should the game do Screen Textures? Provides a good boost to frames\nat the cost of some visual effects not working when disabled.", +#ifdef USE_FBO_OGL + "Allows the game to downsample from a higher resolution than your display in OpenGL renderer mode\nrequires a GPU with atleast OpenGL 3.0 support.", +#endif "Change the depth of the Palette in Palette rendering mod\n 16 bits is like software looks ingame\nwhile 24 bits is how software looks in screenshots.", "Fixes issues that resulted in Textures sticking from the ground sometimes.\n This may be CPU heavy and result in worse performance in some cases.", "Fixes issues that resulted in Textures not being properly skewed\n example: Fences on slopes that didnt show proper.\n This may be CPU heavy and result in worse performance in some cases.", @@ -1508,6 +1515,10 @@ enum op_exp_sprclip, #ifdef HWRENDER op_exp_grscrtx, +#ifdef USE_FBO_OGL + op_exp_fbo, +#endif + op_exp_paldepth, op_exp_spltwal, op_exp_pegging, op_exp_fofzfight, @@ -2909,7 +2920,7 @@ menu_t OP_MonitorToggleDef = menu_t OP_OpenGLOptionsDef = DEFAULTSCROLLSTYLE("M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 30); #endif -menu_t OP_ExpOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_ExpOptionsMenu, &OP_VideoOptionsDef, 30, 20); +menu_t OP_ExpOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_ExpOptionsMenu, &OP_VideoOptionsDef, 30, 10); menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_SCSHOT", OP_ScreenshotOptionsMenu, &OP_DataOptionsDef, 30, 30); @@ -4468,16 +4479,23 @@ void M_Init(void) { OP_VideoOptionsMenu[op_video_ogl].status = IT_DISABLED; OP_ExpOptionsMenu[op_exp_grscrtx].status = IT_DISABLED; +#ifdef USE_FBO_OGL + OP_ExpOptionsMenu[op_exp_fbo].status = IT_DISABLED; +#endif OP_ExpOptionsMenu[op_exp_spltwal].status = IT_DISABLED; OP_ExpOptionsMenu[op_exp_pegging].status = IT_DISABLED; OP_ExpOptionsMenu[op_exp_fofzfight].status = IT_DISABLED; OP_ExpOptionsMenu[op_exp_fofcut].status = IT_DISABLED; } - + if (rendermode == render_opengl) { OP_ExpOptionsMenu[op_exp_ffclip].status = IT_DISABLED; OP_ExpOptionsMenu[op_exp_sprclip].status = IT_DISABLED; +#ifdef USE_FBO_OGL + if (!supportFBO) + OP_ExpOptionsMenu[op_exp_fbo].status = IT_GRAYEDOUT; +#endif } #endif diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index bc932d87f..f90f5bb18 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -80,6 +80,7 @@ #ifdef HWRENDER #include "../hardware/hw_main.h" #include "../hardware/hw_drv.h" +#include "../hardware/r_opengl/r_opengl.h" //for supportFBO // For dynamic referencing of HW rendering functions #include "hwsym_sdl.h" #include "ogl_sdl.h" @@ -215,6 +216,15 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen); //static void Impl_SetWindowName(const char *title); static void Impl_SetWindowIcon(void); +#ifdef USE_FBO_OGL +boolean downsample = false; +void RefreshOGLSDLSurface(void) +{ + if (rendermode == render_opengl) + OglSdlSurface(vid.width, vid.height); +} +#endif + static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen) { static SDL_bool wasfullscreen = SDL_FALSE; @@ -736,11 +746,41 @@ static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which) return raxis; } +#ifdef USE_FBO_OGL +void I_DownSample(void) +{ + if (!cv_grframebuffer.value || !(rendermode == render_opengl) || (!supportFBO)) //no sense to do this crap if we cant benefit from it + { + downsample = false; + return; + } + + int currentDisplayIndex = SDL_GetWindowDisplayIndex(window); + SDL_DisplayMode curmode; + + if (SDL_GetCurrentDisplayMode(currentDisplayIndex, &curmode) == 0) + { + if ((vid.width > curmode.w) || (vid.height > curmode.h)) //check if current resolution is higher than current display resolution + { + downsample = true; + RefreshOGLSDLSurface(); + } + else + downsample = false; // its not so no need to do crap + } + else + downsample = false; // couldnt get display info so turn the thing off +} +#endif + static void Impl_HandleWindowEvent(SDL_WindowEvent evt) { static SDL_bool firsttimeonmouse = SDL_TRUE; static SDL_bool mousefocus = SDL_TRUE; static SDL_bool kbfocus = SDL_TRUE; +#ifdef USE_FBO_OGL + static SDL_bool windowmoved = SDL_FALSE; +#endif switch (evt.event) { @@ -760,6 +800,11 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) break; case SDL_WINDOWEVENT_MAXIMIZED: break; +#ifdef USE_FBO_OGL + case SDL_WINDOWEVENT_MOVED: + windowmoved = SDL_TRUE; + break; +#endif } if (mousefocus && kbfocus) @@ -799,6 +844,12 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) } } +#ifdef USE_FBO_OGL + if (windowmoved && rendermode == render_opengl) + { + I_DownSample(); + } +#endif } static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type) @@ -1877,6 +1928,11 @@ INT32 VID_SetMode(INT32 modeNum) } //Impl_SetWindowName("SRB2Kart "VERSIONSTRING); +#ifdef USE_FBO_OGL + if (rendermode == render_opengl) + I_DownSample(); +#endif + SDLSetMode(vid.width, vid.height, USE_FULLSCREEN); Impl_VideoSetupBuffer(); diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 7c69b2a61..5bb6b7347 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -42,6 +42,7 @@ #include "../i_system.h" #include "hwsym_sdl.h" #include "../m_argv.h" +#include "../i_video.h" #ifdef DEBUG_TO_FILE #include @@ -149,31 +150,54 @@ boolean OglSdlSurface(INT32 w, INT32 h) "- GPU vendor has dropped OpenGL support on your GPU and OS. (Old GPU?)\n" "- GPU drivers are missing or broken. You may need to update your drivers."); } + + SetupGLInfo(); + + SetupGLFunc4(); + + if (majorGL == 1 && minorGL <= 3) // GL_GENERATE_MIPMAP is unavailible for OGL 1.3 and below + supportMipMap = false; + else + supportMipMap = true; + + if (isExtAvailable("GL_EXT_texture_filter_anisotropic", gl_extensions)) + pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy); + else + maximumAnisotropy = 1; + + granisotropicmode_cons_t[1].value = maximumAnisotropy; +#ifdef USE_FBO_OGL + I_DownSample(); +#endif } first_init = true; - if (isExtAvailable("GL_EXT_texture_filter_anisotropic", gl_extensions)) - pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnisotropy); - else - maximumAnisotropy = 1; - - SetupGLInfo(); - - SetupGLFunc4(); - - if (majorGL == 1 && minorGL <= 3) // GL_GENERATE_MIPMAP is unavailible for OGL 1.3 and below - supportMipMap = false; - else - supportMipMap = true; - - granisotropicmode_cons_t[1].value = maximumAnisotropy; - SDL_GL_SetSwapInterval(cv_vidwait.value ? 1 : 0); + // The screen textures need to be flushed if the width or height change so that they be remade for the correct size + if (screen_width != w || screen_height != h) + { + FlushScreenTextures(); +#ifdef USE_FBO_OGL + GLFramebuffer_DeleteAttachments(); +#endif + } + + screen_width = (GLint)w; + screen_height = (GLint)h; + SetModelView(w, h); SetStates(); pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); +#ifdef USE_FBO_OGL + RenderToFramebuffer = FrameBufferEnabled; + GLFramebuffer_Disable(); + + if (RenderToFramebuffer && downsample) + GLFramebuffer_Enable(); +#endif + HWR_Startup(); textureformatGL = cbpp > 16 ? GL_RGBA : GL_RGB5_A1; @@ -198,9 +222,20 @@ void OglSdlFinishUpdate(boolean waitvbl) oldwaitvbl = waitvbl; SDL_GetWindowSize(window, &sdlw, &sdlh); - HWR_MakeScreenFinalTexture(); + +#ifdef USE_FBO_OGL + GLFramebuffer_Disable(); + RenderToFramebuffer = FrameBufferEnabled; +#endif + HWR_DrawScreenFinalTexture(sdlw, sdlh); + +#ifdef USE_FBO_OGL + if (RenderToFramebuffer && downsample) + GLFramebuffer_Enable(); +#endif + SDL_GL_SwapWindow(window); GClipRect(0, 0, realwidth, realheight, NZCLIP_PLANE, FAR_ZCLIP_DEFAULT);