mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 11:28:56 +00:00
241 lines
6.7 KiB
C++
241 lines
6.7 KiB
C++
/*
|
|
* Descent 3
|
|
* Copyright (C) 2024 Parallax Software
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <filesystem>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <vector>
|
|
|
|
#define GL_GLEXT_PROTOTYPES
|
|
#include <SDL_opengl.h>
|
|
|
|
#include "descent.h"
|
|
#include "module.h"
|
|
#include "pserror.h"
|
|
|
|
#if defined(WIN32)
|
|
#define GLFUNCCALL __stdcall
|
|
#elif defined(POSIX)
|
|
#include <unistd.h>
|
|
#define GLFUNCCALL
|
|
#endif
|
|
|
|
// ryan's adds. 04/18/2000.
|
|
// There was a bunch of stuff that was, I guess, not supported by
|
|
// Mesa when Outrage did the original port. So buttloads of code
|
|
// involving glActiveTextureARB() were #ifdef'd to only WIN32.
|
|
// To make use of the extension more generic, platforms that can handle
|
|
// it (Linux and Win32, as far as I care), define
|
|
// _USE_OGL_ACTIVE_TEXTURES, and check that define instead of WIN32 when
|
|
// using the extension.
|
|
#if (!defined(_USE_OGL_ACTIVE_TEXTURES))
|
|
#if (defined(WIN32))
|
|
#define _USE_OGL_ACTIVE_TEXTURES
|
|
#endif
|
|
#endif
|
|
// end ryan's adds.
|
|
|
|
inline void CheckError() {
|
|
#if defined(_DEBUG)
|
|
static auto _dglGetError = reinterpret_cast<GLenum (*)()>(SDL_GL_GetProcAddress("glGetError"));
|
|
auto err = _dglGetError();
|
|
switch (err) {
|
|
case GL_NO_ERROR:
|
|
return;
|
|
case GL_INVALID_ENUM:
|
|
throw std::runtime_error("invalid enum");
|
|
case GL_INVALID_VALUE:
|
|
throw std::runtime_error("invalid value");
|
|
case GL_INVALID_OPERATION:
|
|
throw std::runtime_error("invalid operation");
|
|
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
|
throw std::runtime_error("invalid framebuffer operation");
|
|
case GL_INVALID_INDEX:
|
|
throw std::runtime_error("invalid index");
|
|
default:
|
|
throw std::runtime_error("unknown error: " + std::to_string(err));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
template <typename T> struct FnPtr;
|
|
template <typename Ret, typename... Args>
|
|
struct FnPtr<Ret(Args...)> {
|
|
explicit FnPtr(std::string_view name, bool optional = false);
|
|
|
|
Ret operator()(Args... args) const {
|
|
if constexpr (std::is_same_v<Ret, void>) {
|
|
fn_(args...);
|
|
CheckError();
|
|
} else {
|
|
auto ret = fn_(args...);
|
|
CheckError();
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
operator bool() const { return fn_; }
|
|
|
|
private:
|
|
Ret (GLFUNCCALL *fn_)(Args...);
|
|
};
|
|
|
|
#if defined(DECLARE_OPENGL)
|
|
extern char loadedLibrary[_MAX_PATH];
|
|
static module OpenGLDLLInst;
|
|
|
|
static std::vector<std::tuple<void **, std::string_view, bool>> inits_;
|
|
static void LoadGLFnPtrs() {
|
|
for (auto &[ptr, name, optional] : inits_) {
|
|
*ptr = SDL_GL_GetProcAddress(name.data());
|
|
if (!*ptr && !optional) {
|
|
throw std::runtime_error(std::string{"failed to find "} + name.data());
|
|
}
|
|
}
|
|
inits_.clear();
|
|
}
|
|
|
|
template<typename Ret, typename... Args>
|
|
FnPtr<Ret(Args...)>::FnPtr(std::string_view name, bool optional) : fn_{} {
|
|
inits_.push_back(std::make_tuple(reinterpret_cast<void**>(&fn_), name, optional));
|
|
}
|
|
|
|
static module *LoadOpenGLDLL(const char *dllname) {
|
|
mprintf(0, "Loading OpenGL dll...\n");
|
|
|
|
std::filesystem::path tmp = std::filesystem::current_path();
|
|
std::filesystem::current_path(orig_pwd);
|
|
int rc = SDL_GL_LoadLibrary(dllname[0] ? dllname : nullptr);
|
|
std::filesystem::current_path(tmp);
|
|
|
|
if (rc < 0) {
|
|
const char *sdlErr = SDL_GetError();
|
|
mprintf(0, "OpenGL: Couldn't open library [%s].\n", dllname[0] ? dllname : "system default");
|
|
mprintf(0, "OpenGL: SDL error is [%s].", sdlErr);
|
|
return NULL;
|
|
}
|
|
|
|
strcpy(loadedLibrary, dllname);
|
|
|
|
mprintf(0, "OpenGL dll loading successful.\n");
|
|
|
|
return &OpenGLDLLInst;
|
|
}
|
|
|
|
#define DYNAEXTERN_OPT(Name, Opt) FnPtr<decltype(Name)> const d##Name{#Name, Opt}
|
|
#define DYNAEXTERN(Name) DYNAEXTERN_OPT(Name, false)
|
|
#else
|
|
#define DYNAEXTERN(Name) extern FnPtr<decltype(Name)> const d##Name
|
|
#endif
|
|
|
|
DYNAEXTERN(glAttachShader);
|
|
DYNAEXTERN(glBindAttribLocation);
|
|
DYNAEXTERN(glBindBuffer);
|
|
DYNAEXTERN(glBindTexture);
|
|
DYNAEXTERN(glBindVertexArray);
|
|
DYNAEXTERN(glBlendFunc);
|
|
DYNAEXTERN(glBufferData);
|
|
DYNAEXTERN(glBufferSubData);
|
|
DYNAEXTERN(glClear);
|
|
DYNAEXTERN(glClearColor);
|
|
DYNAEXTERN(glColor3ub);
|
|
DYNAEXTERN(glColor4f);
|
|
DYNAEXTERN(glColor4ub);
|
|
DYNAEXTERN(glColorPointer);
|
|
DYNAEXTERN(glCompileShader);
|
|
DYNAEXTERN(glCreateProgram);
|
|
DYNAEXTERN(glCreateShader);
|
|
DYNAEXTERN(glDeleteBuffers);
|
|
DYNAEXTERN(glDeleteProgram);
|
|
DYNAEXTERN(glDeleteShader);
|
|
DYNAEXTERN(glDeleteTextures);
|
|
DYNAEXTERN(glDeleteVertexArrays);
|
|
DYNAEXTERN(glDepthFunc);
|
|
DYNAEXTERN(glDepthMask);
|
|
DYNAEXTERN(glDepthRange);
|
|
DYNAEXTERN(glDisable);
|
|
DYNAEXTERN(glDisableClientState);
|
|
DYNAEXTERN(glDrawArrays);
|
|
DYNAEXTERN(glEnable);
|
|
DYNAEXTERN(glEnableClientState);
|
|
DYNAEXTERN(glEnableVertexAttribArray);
|
|
DYNAEXTERN(glFlush);
|
|
DYNAEXTERN(glFogf);
|
|
DYNAEXTERN(glFogfv);
|
|
DYNAEXTERN(glFogi);
|
|
DYNAEXTERN(glGenBuffers);
|
|
DYNAEXTERN(glGenVertexArrays);
|
|
DYNAEXTERN(glGetError);
|
|
DYNAEXTERN(glGetIntegerv);
|
|
DYNAEXTERN(glGetProgramInfoLog);
|
|
DYNAEXTERN(glGetProgramiv);
|
|
DYNAEXTERN(glGetShaderInfoLog);
|
|
DYNAEXTERN(glGetShaderiv);
|
|
DYNAEXTERN(glGetString);
|
|
DYNAEXTERN(glGetStringi);
|
|
DYNAEXTERN(glHint);
|
|
DYNAEXTERN(glLinkProgram);
|
|
DYNAEXTERN(glLoadIdentity);
|
|
DYNAEXTERN(glLoadMatrixf);
|
|
DYNAEXTERN(glMatrixMode);
|
|
DYNAEXTERN(glOrtho);
|
|
DYNAEXTERN(glPixelStorei);
|
|
DYNAEXTERN(glPolygonOffset);
|
|
DYNAEXTERN(glReadPixels);
|
|
DYNAEXTERN(glScissor);
|
|
DYNAEXTERN(glShaderSource);
|
|
DYNAEXTERN(glTexCoord2f);
|
|
DYNAEXTERN(glTexCoord4fv);
|
|
DYNAEXTERN(glTexCoordPointer);
|
|
DYNAEXTERN(glTexEnvf);
|
|
DYNAEXTERN(glTexImage2D);
|
|
DYNAEXTERN(glTexParameteri);
|
|
DYNAEXTERN(glTexSubImage2D);
|
|
DYNAEXTERN(glUseProgram);
|
|
DYNAEXTERN(glVertexAttribPointer);
|
|
DYNAEXTERN(glVertexPointer);
|
|
DYNAEXTERN(glViewport);
|
|
|
|
// FBO entry points for render-to-texture ...
|
|
DYNAEXTERN(glBindFramebufferEXT);
|
|
DYNAEXTERN(glBindRenderbufferEXT);
|
|
DYNAEXTERN(glBlitFramebufferEXT);
|
|
DYNAEXTERN(glCheckFramebufferStatusEXT);
|
|
DYNAEXTERN(glDeleteFramebuffersEXT);
|
|
DYNAEXTERN(glDeleteRenderbuffersEXT);
|
|
DYNAEXTERN(glFramebufferRenderbufferEXT);
|
|
DYNAEXTERN(glGenFramebuffersEXT);
|
|
DYNAEXTERN(glGenRenderbuffersEXT);
|
|
DYNAEXTERN(glRenderbufferStorageEXT);
|
|
|
|
#if defined(_USE_OGL_ACTIVE_TEXTURES)
|
|
DYNAEXTERN_OPT(glActiveTextureARB, true);
|
|
DYNAEXTERN_OPT(glClientActiveTextureARB, true);
|
|
DYNAEXTERN_OPT(glMultiTexCoord4f, true);
|
|
#endif
|
|
|
|
#if defined(WIN32)
|
|
DYNAEXTERN(wglCreateContext);
|
|
DYNAEXTERN(wglDeleteContext);
|
|
DYNAEXTERN(wglGetProcAddress);
|
|
DYNAEXTERN(wglMakeCurrent);
|
|
#endif
|