1 /* Emacs style mode select   -*- C++ -*-
2  *-----------------------------------------------------------------------------
3  *
4  *
5  *  PrBoom: a Doom port merged with LxDoom and LSDLDoom
6  *  based on BOOM, a modified and improved DOOM engine
7  *  Copyright (C) 1999 by
8  *  id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9  *  Copyright (C) 1999-2000 by
10  *  Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11  *  Copyright 2005, 2006 by
12  *  Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27  *  02111-1307, USA.
28  *
29  * DESCRIPTION:
30  *   Thanks Roman "Vortex" Marchenko
31  *---------------------------------------------------------------------
32  */
33 
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37 
38 #include "gl_opengl.h"
39 
40 #include <SDL.h>
41 
42 #include "gl_intern.h"
43 
44 #include "i_main.h"
45 #include "lprintf.h"
46 
47 dboolean gl_use_FBO = false;
48 
49 #ifdef USE_FBO_TECHNIQUE
50 GLuint glSceneImageFBOTexID = 0;
51 GLuint glDepthBufferFBOTexID = 0;
52 GLuint glSceneImageTextureFBOTexID = 0;
53 int SceneInTexture = false;
54 static dboolean gld_CreateScreenSizeFBO(void);
55 #endif
56 
57 //e6y: motion bloor
58 int gl_motionblur;
59 int gl_use_motionblur = false;
60 const char *gl_motionblur_minspeed;
61 const char *gl_motionblur_att_a;
62 const char *gl_motionblur_att_b;
63 const char *gl_motionblur_att_c;
64 int MotionBlurOn;
65 int gl_motionblur_minspeed_pow2 = 0x32 * 0x32 + 0x28 * 0x28;
66 float gl_motionblur_a = 55.0f;
67 float gl_motionblur_b = 1.8f;
68 float gl_motionblur_c = 0.9f;
69 
70 //e6y
71 int gl_invul_bw_method;
72 
73 #ifdef USE_FBO_TECHNIQUE
74 
75 void gld_InitMotionBlur(void);
76 
gld_InitFBO(void)77 void gld_InitFBO(void)
78 {
79   gld_FreeScreenSizeFBO();
80 
81   gl_use_motionblur = gl_ext_framebuffer_object && gl_motionblur && gl_ext_blend_color;
82 
83   gl_use_FBO = (gl_ext_framebuffer_object) && (gl_version >= OPENGL_VERSION_1_3) &&
84     (gl_use_motionblur || !gl_boom_colormaps || gl_has_hires);
85 
86   if (gl_use_FBO)
87   {
88     if (gld_CreateScreenSizeFBO())
89     {
90       // motion blur setup
91       gld_InitMotionBlur();
92     }
93     else
94     {
95       gld_FreeScreenSizeFBO();
96       gl_use_FBO = false;
97       gl_ext_framebuffer_object = false;
98     }
99   }
100 }
101 
gld_CreateScreenSizeFBO(void)102 static dboolean gld_CreateScreenSizeFBO(void)
103 {
104   int status = 0;
105   GLenum internalFormat;
106   dboolean attach_stencil = gl_ext_packed_depth_stencil;// && (gl_has_hires || gl_use_motionblur);
107 
108   if (!gl_ext_framebuffer_object)
109     return false;
110 
111   GLEXT_glGenFramebuffersEXT(1, &glSceneImageFBOTexID);
112   GLEXT_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, glSceneImageFBOTexID);
113 
114   GLEXT_glGenRenderbuffersEXT(1, &glDepthBufferFBOTexID);
115   GLEXT_glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, glDepthBufferFBOTexID);
116 
117   internalFormat = (attach_stencil ? GL_DEPTH_STENCIL_EXT : GL_DEPTH_COMPONENT);
118   GLEXT_glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalFormat, SCREENWIDTH, SCREENHEIGHT);
119 
120   // attach a renderbuffer to depth attachment point
121   GLEXT_glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, glDepthBufferFBOTexID);
122 
123   if (attach_stencil)
124   {
125     // attach a renderbuffer to stencil attachment point
126     GLEXT_glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, glDepthBufferFBOTexID);
127   }
128 
129   glGenTextures(1, &glSceneImageTextureFBOTexID);
130   glBindTexture(GL_TEXTURE_2D, glSceneImageTextureFBOTexID);
131   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, SCREENWIDTH, SCREENHEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
132   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
133   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
134   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
135   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
136 
137   // e6y
138   // Some ATI�s drivers have a bug whereby adding the depth renderbuffer
139   // and then a texture causes the application to crash.
140   // This should be kept in mind when doing any FBO related work and
141   // tested for as it is possible it could be fixed in a future driver revision
142   // thus rendering the problem non-existent.
143   PRBOOM_TRY(EXEPTION_glFramebufferTexture2DEXT)
144   {
145     GLEXT_glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, glSceneImageTextureFBOTexID, 0);
146     status = GLEXT_glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
147   }
148   PRBOOM_EXCEPT(EXEPTION_glFramebufferTexture2DEXT)
149 
150   if (status == GL_FRAMEBUFFER_COMPLETE_EXT)
151   {
152     GLEXT_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
153   }
154   else
155   {
156     lprintf(LO_ERROR, "gld_CreateScreenSizeFBO: Cannot create framebuffer object (error code: %d)\n", status);
157   }
158 
159   return (status == GL_FRAMEBUFFER_COMPLETE_EXT);
160 }
161 
gld_FreeScreenSizeFBO(void)162 void gld_FreeScreenSizeFBO(void)
163 {
164   if (!gl_ext_framebuffer_object)
165     return;
166 
167   GLEXT_glDeleteFramebuffersEXT(1, &glSceneImageFBOTexID);
168   glSceneImageFBOTexID = 0;
169 
170   GLEXT_glDeleteRenderbuffersEXT(1, &glDepthBufferFBOTexID);
171   glDepthBufferFBOTexID = 0;
172 
173   glDeleteTextures(1, &glSceneImageTextureFBOTexID);
174   glSceneImageTextureFBOTexID = 0;
175 }
176 
gld_InitMotionBlur(void)177 void gld_InitMotionBlur(void)
178 {
179   if (gl_use_motionblur)
180   {
181     float f;
182 
183     sscanf(gl_motionblur_minspeed, "%f", &f);
184     sscanf(gl_motionblur_att_a, "%f", &gl_motionblur_a);
185     sscanf(gl_motionblur_att_b, "%f", &gl_motionblur_b);
186     sscanf(gl_motionblur_att_c, "%f", &gl_motionblur_c);
187 
188     gl_motionblur_minspeed_pow2 = (int)(f * f);
189   }
190 }
191 #endif
192