DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 // Tell Mac OS X to shut up about deprecated OpenGL calls 00020 #ifndef GL_SILENCE_DEPRECATION 00021 #define GL_SILENCE_DEPRECATION 00022 #endif 00023 00024 #include <stdlib.h> 00025 #include <math.h> 00026 #include <map> 00027 00028 #include "dosbox.h" 00029 #include "dos_inc.h" 00030 00031 #if C_OPENGL 00032 00033 #include "voodoo_vogl.h" 00034 00035 /* NTS: This causes errors in Linux because MesaGL already defines these */ 00036 #ifdef WIN32 00037 PFNGLMULTITEXCOORD4FVARBPROC __glMultiTexCoord4fvARB = NULL; 00038 PFNGLMULTITEXCOORD4FARBPROC __glMultiTexCoord4fARB = NULL; 00039 PFNGLACTIVETEXTUREARBPROC __glActiveTextureARB = NULL; 00040 #endif 00041 00042 PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL; 00043 PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL; 00044 PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL; 00045 PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL; 00046 PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL; 00047 PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL; 00048 PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL; 00049 PFNGLUNIFORM1IARBPROC glUniform1iARB = NULL; 00050 PFNGLUNIFORM1FARBPROC glUniform1fARB = NULL; 00051 PFNGLUNIFORM2FARBPROC glUniform2fARB = NULL; 00052 PFNGLUNIFORM3FARBPROC glUniform3fARB = NULL; 00053 PFNGLUNIFORM4FARBPROC glUniform4fARB = NULL; 00054 PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL; 00055 PFNGLDETACHOBJECTARBPROC glDetachObjectARB = NULL; 00056 PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL; 00057 PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB = NULL; 00058 PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL; 00059 PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL; 00060 PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; 00061 PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL; 00062 PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB = NULL; 00063 00064 00065 static Bit32s opengl_version = -1; 00066 00067 static bool has_shaders = false; 00068 static bool has_stencil = false; 00069 static bool has_alpha = false; 00070 00071 00072 static INT32 current_begin_mode = -1; 00073 00074 static Bit32s current_depth_mode = -1; 00075 static Bit32s current_depth_func = -1; 00076 00077 static Bit32s current_alpha_enabled = -1; 00078 static Bit32s current_src_rgb_fac = -1; 00079 static Bit32s current_dst_rgb_fac = -1; 00080 static Bit32s current_src_alpha_fac = -1; 00081 static Bit32s current_dst_alpha_fac = -1; 00082 00083 static bool depth_masked = false; 00084 static bool color_masked = false; 00085 static bool alpha_masked = false; 00086 00087 // buffer read/write defaults are back-buffer for double buffered contexts 00088 static bool draw_to_front_buffer = false; 00089 static bool read_from_front_buffer = false; 00090 00091 00092 void VOGL_Reset(void) { 00093 opengl_version = -1; 00094 has_shaders = false; 00095 has_stencil = false; 00096 has_alpha = false; 00097 00098 current_depth_mode=-1; 00099 current_depth_func=-1; 00100 00101 current_alpha_enabled=-1; 00102 current_src_rgb_fac=-1; 00103 current_dst_rgb_fac=-1; 00104 current_src_alpha_fac=-1; 00105 current_dst_alpha_fac=-1; 00106 00107 depth_masked = false; 00108 color_masked = false; 00109 alpha_masked = false; 00110 00111 draw_to_front_buffer = false; 00112 read_from_front_buffer = false; 00113 } 00114 00115 00116 void VOGL_InitVersion(void) { 00117 opengl_version = -1; 00118 00119 char gl_verstr[16]; 00120 const GLubyte* gl_verstr_ub = glGetString(GL_VERSION); 00121 strncpy(gl_verstr, (const char*)gl_verstr_ub, 16); 00122 gl_verstr[15] = 0; 00123 char* gl_ver_minor = strchr(gl_verstr, '.'); 00124 if (gl_ver_minor != NULL) { 00125 gl_ver_minor++; 00126 char* skip = strchr(gl_ver_minor, '.'); 00127 if (skip != NULL) *skip = 0; 00128 } 00129 00130 int ogl_ver = 100; 00131 if (gl_verstr[0] != 0) { 00132 int major = 1; 00133 int minor = 0; 00134 if (strchr(gl_verstr, '.') != NULL) { 00135 if (sscanf(gl_verstr,"%d.%d", &major, &minor) != 2) major = 0; 00136 } else { 00137 if (sscanf(gl_verstr, "%d", &major) != 1) major = 0; 00138 } 00139 if (major > 0) { 00140 ogl_ver = major*100; 00141 if (minor >= 0) { 00142 if (minor < 10) ogl_ver += minor*10; 00143 else ogl_ver += minor; 00144 } 00145 } 00146 } 00147 00148 if (ogl_ver > 0) opengl_version = ogl_ver; 00149 } 00150 00151 void VOGL_ClearShaderFunctions(void) { 00152 glShaderSourceARB = NULL; 00153 glCompileShaderARB = NULL; 00154 glCreateProgramObjectARB = NULL; 00155 glAttachObjectARB = NULL; 00156 glLinkProgramARB = NULL; 00157 glUseProgramObjectARB = NULL; 00158 glUniform1iARB = NULL; 00159 glUniform1fARB = NULL; 00160 glUniform2fARB = NULL; 00161 glUniform3fARB = NULL; 00162 glUniform4fARB = NULL; 00163 glGetUniformLocationARB = NULL; 00164 glDetachObjectARB = NULL; 00165 glDeleteObjectARB = NULL; 00166 glGetObjectParameterivARB = NULL; 00167 glGetInfoLogARB = NULL; 00168 } 00169 00170 bool VOGL_Initialize(void) { 00171 VOGL_ClearShaderFunctions(); 00172 00173 VOGL_InitVersion(); 00174 00175 #ifdef WIN32 00176 __glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glActiveTextureARB")); 00177 if (!__glActiveTextureARB) { 00178 LOG_MSG("opengl: glActiveTextureARB extension not supported"); 00179 return false; 00180 } 00181 00182 __glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glMultiTexCoord4fARB")); 00183 if (!__glMultiTexCoord4fARB) { 00184 LOG_MSG("opengl: glMultiTexCoord4fARB extension not supported"); 00185 return false; 00186 } 00187 00188 __glMultiTexCoord4fvARB = (PFNGLMULTITEXCOORD4FVARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glMultiTexCoord4fvARB")); 00189 if (!__glMultiTexCoord4fvARB) { 00190 LOG_MSG("opengl: glMultiTexCoord4fvARB extension not supported"); 00191 return false; 00192 } 00193 #endif 00194 00195 glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)((uintptr_t)SDL_GL_GetProcAddress("glBlendFuncSeparateEXT")); 00196 if (!glBlendFuncSeparateEXT) { 00197 LOG_MSG("opengl: glBlendFuncSeparateEXT extension not supported"); 00198 return false; 00199 } 00200 00201 glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)((uintptr_t)SDL_GL_GetProcAddress("glGenerateMipmapEXT")); 00202 if (!glGenerateMipmapEXT) { 00203 LOG_MSG("opengl: glGenerateMipmapEXT extension not supported"); 00204 return false; 00205 } 00206 00207 if (VOGL_CheckFeature(VOGL_ATLEAST_V20)) { 00208 const char* extensions = (const char*)glGetString(GL_EXTENSIONS); 00209 if (strstr(extensions, "GL_ARB_shader_objects") && strstr(extensions, "GL_ARB_vertex_shader") && 00210 strstr(extensions, "GL_ARB_fragment_shader")) { 00211 00212 glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glCreateShaderObjectARB")); 00213 if (!glCreateShaderObjectARB) { 00214 LOG_MSG("opengl: shader extensions not supported. Using fixed pipeline"); 00215 } else { 00216 glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glShaderSourceARB")); 00217 if (!glShaderSourceARB) LOG_MSG("opengl: glShaderSourceARB extension not supported"); 00218 00219 glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glCompileShaderARB")); 00220 if (!glCompileShaderARB) LOG_MSG("opengl: glCompileShaderARB extension not supported"); 00221 00222 glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glCreateProgramObjectARB")); 00223 if (!glCreateProgramObjectARB) LOG_MSG("opengl: glCreateProgramObjectARB extension not supported"); 00224 00225 glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glAttachObjectARB")); 00226 if (!glAttachObjectARB) LOG_MSG("opengl: glAttachObjectARB extension not supported"); 00227 00228 glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glLinkProgramARB")); 00229 if (!glLinkProgramARB) LOG_MSG("opengl: glLinkProgramARB extension not supported"); 00230 00231 glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glUseProgramObjectARB")); 00232 if (!glUseProgramObjectARB) LOG_MSG("opengl: glUseProgramObjectARB extension not supported"); 00233 00234 glUniform1iARB = (PFNGLUNIFORM1IARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glUniform1iARB")); 00235 if (!glUniform1iARB) LOG_MSG("opengl: glUniform1iARB extension not supported"); 00236 00237 glUniform1fARB = (PFNGLUNIFORM1FARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glUniform1fARB")); 00238 if (!glUniform1fARB) LOG_MSG("opengl: glUniform1fARB extension not supported"); 00239 00240 glUniform2fARB = (PFNGLUNIFORM2FARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glUniform2fARB")); 00241 if (!glUniform2fARB) LOG_MSG("opengl: glUniform2fARB extension not supported"); 00242 00243 glUniform3fARB = (PFNGLUNIFORM3FARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glUniform3fARB")); 00244 if (!glUniform3fARB) LOG_MSG("opengl: glUniform3fARB extension not supported"); 00245 00246 glUniform4fARB = (PFNGLUNIFORM4FARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glUniform4fARB")); 00247 if (!glUniform4fARB) LOG_MSG("opengl: glUniform4fARB extension not supported"); 00248 00249 glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glGetUniformLocationARB")); 00250 if (!glGetUniformLocationARB) LOG_MSG("opengl: glGetUniformLocationARB extension not supported"); 00251 00252 glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glDetachObjectARB")); 00253 if (!glDetachObjectARB) LOG_MSG("opengl: glDetachObjectARB extension not supported"); 00254 00255 glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glDeleteObjectARB")); 00256 if (!glDeleteObjectARB) LOG_MSG("opengl: glDeleteObjectARB extension not supported"); 00257 00258 glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glGetObjectParameterivARB")); 00259 if (!glGetObjectParameterivARB) LOG_MSG("opengl: glGetObjectParameterivARB extension not supported"); 00260 00261 glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glGetInfoLogARB")); 00262 if (!glGetInfoLogARB) LOG_MSG("opengl: glGetInfoLogARB extension not supported"); 00263 00264 glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glGetAttribLocationARB")); 00265 if (!glGetAttribLocationARB) LOG_MSG("opengl: glGetAttribLocationARB extension not supported"); 00266 00267 glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC)((uintptr_t)SDL_GL_GetProcAddress("glVertexAttrib1fARB")); 00268 if (!glVertexAttrib1fARB) LOG_MSG("opengl: glVertexAttrib1fARB extension not supported"); 00269 00270 if (glShaderSourceARB && glCompileShaderARB && glCreateProgramObjectARB && 00271 glAttachObjectARB && glLinkProgramARB && glUseProgramObjectARB && 00272 glUniform1iARB && glUniform1fARB && glUniform2fARB && glUniform3fARB && 00273 glUniform4fARB && glGetUniformLocationARB && glDetachObjectARB && 00274 glDeleteObjectARB && glGetObjectParameterivARB && glGetInfoLogARB) { 00275 VOGL_FlagFeature(VOGL_HAS_SHADERS); 00276 // LOG_MSG("opengl: shader functionality enabled"); 00277 } else { 00278 VOGL_ClearShaderFunctions(); 00279 } 00280 } 00281 } 00282 } 00283 00284 LOG_MSG("opengl: I am able to use OpenGL to emulate Voodoo graphics"); 00285 return true; 00286 } 00287 00288 00289 bool VOGL_CheckFeature(Bit32u feat) { 00290 switch (feat) { 00291 case VOGL_ATLEAST_V20: 00292 if (opengl_version >= 200) return true; 00293 break; 00294 case VOGL_ATLEAST_V21: 00295 if (opengl_version >= 210) return true; 00296 break; 00297 case VOGL_ATLEAST_V30: 00298 if (opengl_version >= 300) return true; 00299 break; 00300 case VOGL_HAS_SHADERS: 00301 if (has_shaders) return true; 00302 break; 00303 case VOGL_HAS_STENCIL_BUFFER: 00304 if (has_stencil) return true; 00305 break; 00306 case VOGL_HAS_ALPHA_PLANE: 00307 if (has_alpha) return true; 00308 break; 00309 default: 00310 LOG_MSG("opengl: unknown feature queried: %x",feat); 00311 break; 00312 } 00313 00314 return false; 00315 } 00316 00317 void VOGL_FlagFeature(Bit32u feat) { 00318 switch (feat) { 00319 case VOGL_HAS_SHADERS: 00320 has_shaders = true; 00321 break; 00322 case VOGL_HAS_STENCIL_BUFFER: 00323 has_stencil = true; 00324 break; 00325 case VOGL_HAS_ALPHA_PLANE: 00326 has_alpha = true; 00327 break; 00328 default: 00329 LOG_MSG("opengl: unknown feature: %x",feat); 00330 break; 00331 } 00332 } 00333 00334 00335 void VOGL_BeginMode(INT32 new_mode) { 00336 if (current_begin_mode > -1) { 00337 if (new_mode != current_begin_mode) { 00338 glEnd(); 00339 if (new_mode > -1) glBegin((GLenum)new_mode); 00340 current_begin_mode = new_mode; 00341 } 00342 } else { 00343 if (new_mode > -1) { 00344 glBegin((GLenum)new_mode); 00345 current_begin_mode = new_mode; 00346 } 00347 } 00348 } 00349 00350 void VOGL_ClearBeginMode(void) { 00351 if (current_begin_mode > -1) { 00352 glEnd(); 00353 current_begin_mode = -1; 00354 } 00355 } 00356 00357 00358 void VOGL_SetDepthMode(Bit32s mode, Bit32s func) { 00359 if (current_depth_mode!=mode) { 00360 if (mode!=0) { 00361 VOGL_ClearBeginMode(); 00362 glEnable(GL_DEPTH_TEST); 00363 current_depth_mode=1; 00364 if (current_depth_func!=func) { 00365 glDepthFunc((GLenum)(GL_NEVER+func)); 00366 current_depth_func=func; 00367 } 00368 } else { 00369 VOGL_ClearBeginMode(); 00370 glDisable(GL_DEPTH_TEST); 00371 current_depth_mode=0; 00372 } 00373 } else { 00374 if ((mode!=0) && (current_depth_func!=func)) { 00375 VOGL_ClearBeginMode(); 00376 glDepthFunc((GLenum)(GL_NEVER+func)); 00377 current_depth_func=func; 00378 } 00379 } 00380 } 00381 00382 00383 void VOGL_SetAlphaMode(Bit32s enabled_mode,GLuint src_rgb_fac,GLuint dst_rgb_fac, 00384 GLuint src_alpha_fac,GLuint dst_alpha_fac) { 00385 if (current_alpha_enabled!=enabled_mode) { 00386 VOGL_ClearBeginMode(); 00387 if (enabled_mode!=0) { 00388 glEnable(GL_BLEND); 00389 current_alpha_enabled=1; 00390 if ((current_src_rgb_fac!=(Bit32s)src_rgb_fac) || (current_dst_rgb_fac!=(Bit32s)dst_rgb_fac) || 00391 (current_src_alpha_fac!=(Bit32s)src_alpha_fac) || (current_dst_alpha_fac!=(Bit32s)dst_alpha_fac)) { 00392 glBlendFuncSeparateEXT(src_rgb_fac, dst_rgb_fac, src_alpha_fac, dst_alpha_fac); 00393 current_src_rgb_fac=(Bit32s)src_rgb_fac; 00394 current_dst_rgb_fac=(Bit32s)dst_rgb_fac; 00395 current_src_alpha_fac=(Bit32s)src_alpha_fac; 00396 current_dst_alpha_fac=(Bit32s)dst_alpha_fac; 00397 } 00398 } else { 00399 glDisable(GL_BLEND); 00400 current_alpha_enabled=0; 00401 } 00402 } else { 00403 if (current_alpha_enabled!=0) { 00404 if ((current_src_rgb_fac!=(Bit32s)src_rgb_fac) || (current_dst_rgb_fac!=(Bit32s)dst_rgb_fac) || 00405 (current_src_alpha_fac!=(Bit32s)src_alpha_fac) || (current_dst_alpha_fac!=(Bit32s)dst_alpha_fac)) { 00406 VOGL_ClearBeginMode(); 00407 glBlendFuncSeparateEXT(src_rgb_fac, dst_rgb_fac, src_alpha_fac, dst_alpha_fac); 00408 current_src_rgb_fac=(Bit32s)src_rgb_fac; 00409 current_dst_rgb_fac=(Bit32s)dst_rgb_fac; 00410 current_src_alpha_fac=(Bit32s)src_alpha_fac; 00411 current_dst_alpha_fac=(Bit32s)dst_alpha_fac; 00412 } 00413 } 00414 } 00415 } 00416 00417 00418 void VOGL_SetDepthMaskMode(bool masked) { 00419 if (depth_masked!=masked) { 00420 VOGL_ClearBeginMode(); 00421 if (masked) { 00422 glDepthMask(GL_TRUE); 00423 depth_masked=true; 00424 } else { 00425 glDepthMask(GL_FALSE); 00426 depth_masked=false; 00427 } 00428 } 00429 } 00430 00431 00432 void VOGL_SetColorMaskMode(bool cmasked, bool amasked) { 00433 if ((color_masked!=cmasked) || (alpha_masked!=amasked)) { 00434 color_masked=cmasked; 00435 alpha_masked=amasked; 00436 GLboolean cm = (color_masked ? GL_TRUE : GL_FALSE); 00437 GLboolean am = (alpha_masked ? GL_TRUE : GL_FALSE); 00438 glColorMask(cm,cm,cm,am); 00439 } 00440 } 00441 00442 00443 void VOGL_SetDrawMode(bool front_draw) { 00444 if (draw_to_front_buffer!=front_draw) { 00445 VOGL_ClearBeginMode(); 00446 if (front_draw) glDrawBuffer(GL_FRONT); 00447 else glDrawBuffer(GL_BACK); 00448 draw_to_front_buffer=front_draw; 00449 } 00450 } 00451 00452 00453 void VOGL_SetReadMode(bool front_read) { 00454 VOGL_ClearBeginMode(); 00455 00456 if (read_from_front_buffer!=front_read) { 00457 if (front_read) glReadBuffer(GL_FRONT); 00458 else glReadBuffer(GL_BACK); 00459 read_from_front_buffer=front_read; 00460 } 00461 } 00462 00463 #endif