qzdoom-gpl/src/gl/system/gl_interface.cpp
Christoph Oelckers 7d3beb665b - rewrote vertex buffer code to require GL_ARB_BUFFER_STORAGE extension.
This means it won't work anymore on anything that doesn't support OpenGL 4.0, but I don't think this is a problem. On older NVidia cards performance gains could not be seen and on older AMDs using the vertex buffer was even worse as long as it got mixed with immediate mode rendering.
2014-05-10 21:47:07 +02:00

309 lines
10 KiB
C++

/*
** r_opengl.cpp
**
** OpenGL system interface
**
**---------------------------------------------------------------------------
** Copyright 2005 Tim Stump
** Copyright 2005-2013 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
** 4. Full disclosure of the entire project's source code, except for third
** party libraries is mandatory. (NOTE: This clause is non-negotiable!)
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "gl/system/gl_system.h"
#include "tarray.h"
#include "doomtype.h"
#include "m_argv.h"
#include "zstring.h"
#include "version.h"
#include "i_system.h"
#include "v_text.h"
#include "gl/system/gl_interface.h"
#include "gl/system/gl_cvars.h"
#if defined (__unix__) || defined (__APPLE__)
#define PROC void*
#define LPCSTR const char*
#include <SDL.h>
#define wglGetProcAddress(x) (*SDL_GL_GetProcAddress)(x)
#endif
static void APIENTRY glBlendEquationDummy (GLenum mode);
static TArray<FString> m_Extensions;
RenderContext gl;
int occlusion_type=0;
PROC myGetProcAddress(LPCSTR proc)
{
PROC p = wglGetProcAddress(proc);
if (p == NULL) I_Error("Fatal: GL function '%s' not found.", proc);
return p;
}
//==========================================================================
//
//
//
//==========================================================================
static void CollectExtensions()
{
const char *supported = NULL;
char *extensions, *extension;
supported = (char *)glGetString(GL_EXTENSIONS);
if (supported)
{
extensions = new char[strlen(supported) + 1];
strcpy(extensions, supported);
extension = strtok(extensions, " ");
while(extension)
{
m_Extensions.Push(FString(extension));
extension = strtok(NULL, " ");
}
delete [] extensions;
}
}
//==========================================================================
//
//
//
//==========================================================================
static bool CheckExtension(const char *ext)
{
for (unsigned int i = 0; i < m_Extensions.Size(); ++i)
{
if (m_Extensions[i].CompareNoCase(ext) == 0) return true;
}
return false;
}
//==========================================================================
//
//
//
//==========================================================================
static void InitContext()
{
gl.flags=0;
}
//==========================================================================
//
//
//
//==========================================================================
void gl_LoadExtensions()
{
InitContext();
CollectExtensions();
const char *version = (const char*)glGetString(GL_VERSION);
// Don't even start if it's lower than 1.3
if (strcmp(version, "2.0") < 0)
{
I_FatalError("Unsupported OpenGL version.\nAt least GL 2.0 is required to run " GAMENAME ".\n");
}
// This loads any function pointers and flags that require a vaild render context to
// initialize properly
gl.shadermodel = 0; // assume no shader support
gl.vendorstring=(char*)glGetString(GL_VENDOR);
if (CheckExtension("GL_ARB_texture_compression")) gl.flags|=RFL_TEXTURE_COMPRESSION;
if (CheckExtension("GL_EXT_texture_compression_s3tc")) gl.flags|=RFL_TEXTURE_COMPRESSION_S3TC;
if (CheckExtension("GL_ARB_buffer_storage")) gl.flags |= RFL_BUFFER_STORAGE;
gl.version = strtod((char*)glGetString(GL_VERSION), NULL);
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&gl.max_texturesize);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Rules:
// SM4 will always use shaders. No option to switch them off is needed here.
// SM3 has shaders optional but they are off by default (they will have a performance impact
// SM2 only uses shaders for colormaps on camera textures and has no option to use them in general.
// On SM2 cards the shaders will be too slow and show visual bugs (at least on GF 6800.)
if (strcmp((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION), "1.3") >= 0) gl.shadermodel = 4;
else if (CheckExtension("GL_NV_vertex_program3")) gl.shadermodel = 3;
else if (!strstr(gl.vendorstring, "NVIDIA")) gl.shadermodel = 3;
else gl.shadermodel = 2; // Only for older NVidia cards which had notoriously bad shader support.
// Command line overrides for testing and problem cases.
if (Args->CheckParm("-sm2") && gl.shadermodel > 2) gl.shadermodel = 2;
else if (Args->CheckParm("-sm3") && gl.shadermodel > 3) gl.shadermodel = 3;
if (gl.version >= 3.f)
{
gl.flags|=RFL_FRAMEBUFFER;
}
}
//==========================================================================
//
//
//
//==========================================================================
void gl_PrintStartupLog()
{
Printf ("GL_VENDOR: %s\n", glGetString(GL_VENDOR));
Printf ("GL_RENDERER: %s\n", glGetString(GL_RENDERER));
Printf ("GL_VERSION: %s\n", glGetString(GL_VERSION));
Printf ("GL_SHADING_LANGUAGE_VERSION: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
Printf ("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));
int v;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &v);
Printf("Max. texture size: %d\n", v);
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &v);
Printf ("Max. texture units: %d\n", v);
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &v);
Printf ("Max. fragment uniforms: %d\n", v);
if (gl.shadermodel == 4) gl.maxuniforms = v;
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &v);
Printf ("Max. vertex uniforms: %d\n", v);
glGetIntegerv(GL_MAX_VARYING_FLOATS, &v);
Printf ("Max. varying: %d\n", v);
glGetIntegerv(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, &v);
Printf ("Max. combined uniforms: %d\n", v);
glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &v);
Printf ("Max. combined uniform blocks: %d\n", v);
}
//==========================================================================
//
//
//
//==========================================================================
static void APIENTRY glBlendEquationDummy (GLenum mode)
{
// If this is not supported all non-existent modes are
// made to draw nothing.
if (mode == GL_FUNC_ADD)
{
glColorMask(true, true, true, true);
}
else
{
glColorMask(false, false, false, false);
}
}
//==========================================================================
//
//
//
//==========================================================================
void gl_SetTextureMode(int type)
{
static float white[] = {1.f,1.f,1.f,1.f};
if (type == TM_MASK)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
}
else if (type == TM_OPAQUE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
}
else if (type == TM_INVERT)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
}
else if (type == TM_INVERTOPAQUE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
}
else // if (type == TM_MODULATE)
{
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
}
//} // extern "C"