Support for multiple OpenGL Loaders: epoxy, glbinding, glad, glew

master
Dorian Wouters 2017-02-24 21:15:22 -05:00
parent 72ec16aefb
commit 12fdcc237f
No known key found for this signature in database
GPG Key ID: 6E9DA8063322434B
36 changed files with 684 additions and 137 deletions

View File

@ -92,16 +92,15 @@ endif()
find_package(Optional REQUIRED)
pkg_search_module(EPOXY REQUIRED epoxy)
pkg_search_module(GLFW REQUIRED glfw3)
pkg_search_module(SQLITE3 REQUIRED sqlite3)
pkg_search_module(LIBSODIUM REQUIRED libsodium)
include_directories(BEFORE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
${ETC_INCLUDE_DIRS}
${LUA_INCLUDE_DIR}
${LZFX_INCLUDE_DIRS}
${ENET_INCLUDE_DIRS}
${EPOXY_INCLUDE_DIRS}
${GLFW_INCLUDE_DIRS}
${LIBSODIUM_INCLUDE_DIRS}
${SQLITE3_INCLUDE_DIRS}
@ -114,27 +113,64 @@ include_directories(BEFORE
#file(GLOB_RECURSE FILELIST "*.h" "*.hpp" "*.cpp")
#add_custom_target(files SOURCES ${FILELIST})
# Add diggler executable target
### Allow subdirs to add params to the `diggler` target
# Sources
set_property(GLOBAL PROPERTY DIGGLER_SOURCE_FILES "")
macro(diggler_add_sources)
function(diggler_add_sources)
get_property(SRCS GLOBAL PROPERTY DIGGLER_SOURCE_FILES)
list(APPEND SRCS ${ARGV})
set_property(GLOBAL PROPERTY DIGGLER_SOURCE_FILES "${SRCS}")
endmacro(diggler_add_sources)
endfunction(diggler_add_sources)
# Definitions
set_property(GLOBAL PROPERTY DIGGLER_DEFINITIONS "")
function(diggler_add_definition)
get_property(DEFS GLOBAL PROPERTY DIGGLER_DEFINITIONS)
list(APPEND DEFS "${ARGV0}")
set_property(GLOBAL PROPERTY DIGGLER_DEFINITIONS "${DEFS}")
endfunction(diggler_add_definition)
# Include directories
set_property(GLOBAL PROPERTY DIGGLER_INCLUDE_DIRECTORIES "")
function(diggler_include_directories)
get_property(INCDIRS GLOBAL PROPERTY DIGGLER_INCLUDE_DIRECTORIES)
list(APPEND INCDIRS ${ARGV})
set_property(GLOBAL PROPERTY DIGGLER_INCLUDE_DIRECTORIES "${INCDIRS}")
endfunction(diggler_include_directories)
# Link libraries
set_property(GLOBAL PROPERTY DIGGLER_LINK_LIBRARIES "")
function(diggler_link_libraries)
get_property(LIBS GLOBAL PROPERTY DIGGLER_LINK_LIBRARIES)
list(APPEND LIBS ${ARGV})
set_property(GLOBAL PROPERTY DIGGLER_LINK_LIBRARIES "${LIBS}")
endfunction(diggler_link_libraries)
set(DIGGLER_USED_ROOT_CMAKELISTS TRUE)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/src")
### Create target and apply parameters
# Include directories
get_property(INCDIRS GLOBAL PROPERTY DIGGLER_INCLUDE_DIRECTORIES)
include_directories(BEFORE ${INCDIRS})
# Sources
get_property(SRCS GLOBAL PROPERTY DIGGLER_SOURCE_FILES)
add_executable(diggler ${SRCS})
# Definitions
get_property(DEFS GLOBAL PROPERTY DIGGLER_DEFINITIONS)
target_compile_definitions(diggler PUBLIC ${DEFS})
# Link libraries
get_property(LIBS GLOBAL PROPERTY DIGGLER_LINK_LIBRARIES)
target_link_libraries(diggler
${LIBS}
${ETC_LIBRARIES}
${LUA_LIBRARY}
${LZFX_LIBRARIES}
${ENET_LIBRARIES}
${EPOXY_LIBRARIES}
${GLFW_LIBRARIES}
${LIBSODIUM_LIBRARIES}
${SQLITE3_LIBRARIES}

2
include/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
KHR
glad

1
src/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
glad.c

View File

@ -1,7 +1,7 @@
#ifndef CLOUDS_HPP
#define CLOUDS_HPP
#ifndef DIGGLER_CLOUDS_HPP
#define DIGGLER_CLOUDS_HPP
#include <epoxy/gl.h>
#include "render/gl/OpenGL.hpp"
#include <glm/glm.hpp>
#include "render/gl/VBO.hpp"
@ -37,4 +37,4 @@ public:
}
#endif
#endif /* DIGGLER_CLOUDS_HPP */

View File

@ -1,7 +1,9 @@
#include "EscMenu.hpp"
#include <epoxy/gl.h>
#include "render/gl/OpenGL.hpp"
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "Game.hpp"
#include "ui/Text.hpp"
#include "ui/Button.hpp"

View File

@ -27,54 +27,58 @@ static void APIENTRY glDebugCallback(GLenum source, GLenum type, GLuint id,
GLenum severity, GLsizei length, const GLchar *message, const void *userParam) {
const char *sourceStr = "???";
switch (source) {
case GL_DEBUG_SOURCE_API:
sourceStr = "API";
break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
sourceStr = "WIN";
break;
case GL_DEBUG_SOURCE_SHADER_COMPILER:
sourceStr = "SHC";
break;
case GL_DEBUG_SOURCE_THIRD_PARTY:
sourceStr = "3PT";
break;
case GL_DEBUG_SOURCE_APPLICATION:
sourceStr = "APP";
break;
case GL_DEBUG_SOURCE_OTHER:
sourceStr = "OTH";
break;
case GL_DEBUG_SOURCE_API:
sourceStr = "API";
break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
sourceStr = "WIN";
break;
case GL_DEBUG_SOURCE_SHADER_COMPILER:
sourceStr = "SHC";
break;
case GL_DEBUG_SOURCE_THIRD_PARTY:
sourceStr = "3PT";
break;
case GL_DEBUG_SOURCE_APPLICATION:
sourceStr = "APP";
break;
case GL_DEBUG_SOURCE_OTHER:
sourceStr = "OTH";
break;
default:
break;
}
const char *typeStr = "???";
switch (type) {
case GL_DEBUG_TYPE_ERROR:
typeStr = "ERR";
break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
typeStr = "DEP";
break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
typeStr = "UND";
break;
case GL_DEBUG_TYPE_PORTABILITY:
typeStr = "PRT";
break;
case GL_DEBUG_TYPE_PERFORMANCE:
typeStr = "PRF";
break;
case GL_DEBUG_TYPE_MARKER:
typeStr = "MKR";
break;
case GL_DEBUG_TYPE_PUSH_GROUP:
typeStr = "GP+";
break;
case GL_DEBUG_TYPE_POP_GROUP:
typeStr = "GP-";
break;
case GL_DEBUG_TYPE_OTHER:
typeStr = "OTH";
break;
case GL_DEBUG_TYPE_ERROR:
typeStr = "ERR";
break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
typeStr = "DEP";
break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
typeStr = "UND";
break;
case GL_DEBUG_TYPE_PORTABILITY:
typeStr = "PRT";
break;
case GL_DEBUG_TYPE_PERFORMANCE:
typeStr = "PRF";
break;
case GL_DEBUG_TYPE_MARKER:
typeStr = "MKR";
break;
case GL_DEBUG_TYPE_PUSH_GROUP:
typeStr = "GP+";
break;
case GL_DEBUG_TYPE_POP_GROUP:
typeStr = "GP-";
break;
case GL_DEBUG_TYPE_OTHER:
typeStr = "OTH";
break;
default:
break;
}
const char *severityStr = "??";
switch (severity) {
@ -90,6 +94,8 @@ static void APIENTRY glDebugCallback(GLenum source, GLenum type, GLuint id,
case GL_DEBUG_SEVERITY_NOTIFICATION:
severityStr = "NT";
break;
default:
break;
}
char line[3 + 1 + 3 + 1 + 2 + 2 + 1];
std::snprintf(line, sizeof(line)/sizeof(line[0]), "%3s %3s %2s] ", sourceStr, typeStr, severityStr);
@ -101,7 +107,7 @@ GameWindow::GameWindow(Game *G) : G(G) {
if (InstanceCount++ == 0) {
glfwSetErrorCallback(glfwErrorCallback);
int glfwStatus = glfwInit();
if (glfwStatus != GL_TRUE) {
if (glfwStatus != GLFW_TRUE) {
std::ostringstream err;
err << "GLFW init failed (" << glfwStatus << ')';
throw std::runtime_error(err.str());
@ -122,7 +128,7 @@ GameWindow::GameWindow(Game *G) : G(G) {
//glfwWindowHint(GLFW_STENCIL_BITS, 8);
#ifdef DEBUG
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
#endif
m_window = glfwCreateWindow(m_w, m_h, "Diggler", nullptr, nullptr);
@ -131,6 +137,9 @@ GameWindow::GameWindow(Game *G) : G(G) {
throw std::runtime_error("GLFW window creation failed");
}
glfwMakeContextCurrent(m_window);
Render::gl::OpenGL::init();
#ifdef DEBUG
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
glDebugMessageCallback(glDebugCallback, nullptr);
@ -173,7 +182,14 @@ GameWindow::GameWindow(Game *G) : G(G) {
#endif
;
getOutputStreamRaw() << "-- Epoxy GL" << (epoxy_is_desktop_gl() ? "" : "ES") << epoxy_gl_version() << std::endl;
auto glver = Render::gl::OpenGL::version();
getOutputStreamRaw() << "-- " <<
Render::gl::OpenGL::loaderName() << ' ' <<
Render::gl::OpenGL::loaderVersion() << " -- GL" <<
(glver.isGLES ? "ES" : "") << ' ' <<
glver.major << '.' << glver.minor <<
(glver.isCore ? " Core" : "") <<
(glver.isForward ? " FC" : "") << ' ' << std::endl;
if (InstanceCount == 1) { // If we're the first instance
const uint8 *GL_version = glGetString(GL_VERSION);

View File

@ -1,10 +1,16 @@
#ifndef GAME_WINDOW_HPP
#define GAME_WINDOW_HPP
#include <memory>
#include <alc.h>
#include <epoxy/gl.h>
#include "render/gl/OpenGL.hpp"
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <glm/detail/type_mat.hpp>
#include "Platform.hpp"
#include "ui/Manager.hpp"

View File

@ -1,13 +1,13 @@
#ifndef PLAYER_HPP
#define PLAYER_HPP
#ifndef DIGGLER_PLAYER_HPP
#define DIGGLER_PLAYER_HPP
#include "Platform.hpp"
#include <functional>
#include <list>
#include <memory>
#include "render/gl/OpenGL.hpp"
#include <glm/glm.hpp>
#include <epoxy/gl.h>
#include "platform/PreprocUtils.hpp"
#include "network/Network.hpp"
@ -75,4 +75,4 @@ public:
}
#endif
#endif /* DIGGLER_PLAYER_HPP */

View File

@ -40,9 +40,9 @@ Texture::Texture(const std::string &path, PixelFormat format) {
case PixelFormat::RGBA:
stbiFormat = STBI_rgb_alpha;
break;
case PixelFormat::Monochrome8:
/* case PixelFormat::Monochrome8:
stbiFormat = STBI_grey;
break;
break;*/
}
int width, height, channels;
unsigned char *ptr = nullptr;
@ -89,7 +89,7 @@ GLenum getFilterGlConstant(Texture::Filter filter) {
case Texture::Filter::Nearest:
return GL_NEAREST;
}
return 0;
return GL_INVALID_ENUM;
}
void Texture::setFiltering(Filter min, Filter mag) {
@ -100,7 +100,7 @@ void Texture::setFiltering(Filter min, Filter mag) {
PopBoundTex();
}
static GLint getWrapGlConstant(Texture::Wrapping wrap) {
static GLenum getWrapGlConstant(Texture::Wrapping wrap) {
switch (wrap) {
case Texture::Wrapping::ClampEdge:
return GL_CLAMP_TO_EDGE;
@ -111,7 +111,7 @@ static GLint getWrapGlConstant(Texture::Wrapping wrap) {
case Texture::Wrapping::MirroredRepeat:
return GL_MIRRORED_REPEAT;
}
return 0;
return GL_INVALID_ENUM;
}
void Texture::setWrapping(Wrapping s, Wrapping t) {
@ -130,9 +130,9 @@ void Texture::setPlaceholder() {
case PixelFormat::RGBA:
pxLength = 4;
break;
case PixelFormat::Monochrome8:
/* case PixelFormat::Monochrome8:
pxLength = 1;
break;
break;*/
}
unsigned char *white = new unsigned char[m_w * m_h * pxLength];
memset(white, 255, m_w * m_h * pxLength);
@ -148,11 +148,11 @@ static GLenum getGlTexFormat(Texture::PixelFormat fmt) {
case Texture::PixelFormat::RGBA:
return GL_RGBA;
break;
case Texture::PixelFormat::Monochrome8:
/* case Texture::PixelFormat::Monochrome8:
return GL_R8;
break;
break;*/
}
return 0;
return GL_INVALID_ENUM;
}
void Texture::setTexture(uint w, uint h, const uint8_t *data, PixelFormat format) {
@ -223,9 +223,9 @@ uint Texture::requiredBufferSize() {
case PixelFormat::RGBA:
texelSize = 4;
break;
case PixelFormat::Monochrome8:
/* case PixelFormat::Monochrome8:
texelSize = 1;
break;
break; */
}
return m_w * m_h * texelSize;
}

View File

@ -1,15 +1,17 @@
#ifndef TEXTURE_HPP
#define TEXTURE_HPP
#include <epoxy/gl.h>
#ifndef DIGGLER_TEXTURE_HPP
#define DIGGLER_TEXTURE_HPP
#include <string>
#include "render/gl/OpenGL.hpp"
namespace Diggler {
class Texture {
public:
enum class PixelFormat {
RGB,
RGBA,
Monochrome8
// Monochrome8
};
enum class Filter {
Nearest,
@ -72,4 +74,4 @@ public:
};
}
#endif
#endif /* DIGGLER_TEXTURE_HPP */

View File

@ -117,25 +117,29 @@ Registry::Registry() :
br.commit();
}
m_texturePacker = new TexturePacker(64*8, 64*8);
m_texturePacker->freezeTexUpdate(true);
if (GlobalProperties::IsClient) {
m_texturePacker = new TexturePacker(64*8, 64*8);
m_texturePacker->freezeTexUpdate(true);
// Valve checkerboard! :)
unk1 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\xFF\x00\xFF\xFF\x00\xFF\x00\x00\x00");
unk2 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\x00\x00\xFF\x00\x00\xFF\x00\x00\x00");
unk3 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\x00\xFF\x00\x00\xFF\x00\x00\x00\x00");
unk4 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\xFF\x00\x00\xFF\x00\x00\x00\x00\x00");
unk5 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\x00\xFF\xFF\x00\xFF\xFF\x00\x00\x00");
unk6 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\xFF\xFF\x00\xFF\xFF\x00\x00\x00\x00");
unk7 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00");
unk8 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\x00\x0F\x00\x00\x0F\x00\x00\x00\x00");
// Valve checkerboard! :)
unk1 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\xFF\x00\xFF\xFF\x00\xFF\x00\x00\x00");
unk2 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\x00\x00\xFF\x00\x00\xFF\x00\x00\x00");
unk3 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\x00\xFF\x00\x00\xFF\x00\x00\x00\x00");
unk4 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\xFF\x00\x00\xFF\x00\x00\x00\x00\x00");
unk5 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\x00\xFF\xFF\x00\xFF\xFF\x00\x00\x00");
unk6 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\xFF\xFF\x00\xFF\xFF\x00\x00\x00\x00");
unk7 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00");
unk8 = m_texturePacker->add(2, 2, 3, (uint8*)"\x00\x00\x00\x00\x0F\x00\x00\x0F\x00\x00\x00\x00");
m_texturePacker->freezeTexUpdate(false);
m_atlas = m_texturePacker->getAtlas();
m_texturePacker->freezeTexUpdate(false);
m_atlas = m_texturePacker->getAtlas();
}
}
Registry::~Registry() {
delete m_texturePacker;
if (GlobalProperties::IsClient) {
delete m_texturePacker;
}
}
TexturePacker::Coord Registry::addTexture(const std::string &texName,

View File

@ -0,0 +1,15 @@
#ifndef DIGGLER_PLATFORM_FIXES_GLIBC
#define DIGGLER_PLATFORM_FIXES_GLIBC
// Disable some names (major, minor, makedev) inappropriately reserved as macros
// by the morons glibc devs are.
// https://bugzilla.redhat.com/show_bug.cgi?id=130601
#ifndef _SYS_SYSMACROS_H
#define _SYS_SYSMACROS_H 1
#else
#undef major
#undef minor
#undef makedev
#endif
#endif /* DIGGLER_PLATFORM_FIXES_GLIBC */

12
src/platform/Fixes.hpp Normal file
View File

@ -0,0 +1,12 @@
#ifndef DIGGLER_PLATFORM_FIXES
#define DIGGLER_PLATFORM_FIXES
#ifdef _GNU_SOURCE
#include "Fixes.glibc.hpp"
#endif
#ifdef _WIN32
#include "Fixes.windows.hpp"
#endif
#endif /* DIGGLER_PLATFORM_FIXES */

View File

@ -0,0 +1,12 @@
#ifndef DIGGLER_PLATFORM_FIXES_WINDOWS
#define DIGGLER_PLATFORM_FIXES_WINDOWS
// Microsoft has a shitty habit of polluting the user namespace with frequently used names
#define WIN32_LEAN_AND_MEAN 1
#define NOMINMAX 1
#include <windows.h>
#undef near
#undef far
#endif /* DIGGLER_PLATFORM_FIXES_WINDOWS */

View File

@ -1,10 +1,51 @@
set(DIGGLER_ENABLE_GL_RENDERER TRUE CACHE BOOL "Enable OpenGL (ES) renderer")
set(DIGGLER_ENABLE_VK_RENDERER TRUE CACHE BOOL "Enable Vulkan renderer")
if(DIGGLER_ENABLE_GL_RENDERER)
set(DIGGLER_GL_LOADER "libepoxy" CACHE STRING
"OpenGL loader to use. One of 'libepoxy', 'glad', 'glbinding', 'glew'")
if (DIGGLER_ENABLE_GL_RENDERER)
if ("${DIGGLER_GL_LOADER}" STREQUAL "libepoxy")
pkg_search_module(EPOXY REQUIRED epoxy)
set(DIGGLER_GL_USE_LIBEPOXY TRUE)
set(DIGGLER_GL_LOADER_SUPPORTED TRUE)
diggler_add_definition("DIGGLER_GL_USE_LIBEPOXY")
diggler_include_directories(${EPOXY_INCLUDE_DIRS})
diggler_link_libraries(${EPOXY_LIBRARIES})
endif()
if ("${DIGGLER_GL_LOADER}" STREQUAL "glad")
set(DIGGLER_GL_USE_GLAD TRUE)
set(DIGGLER_GL_LOADER_SUPPORTED TRUE)
diggler_add_definition("DIGGLER_GL_USE_GLAD")
diggler_add_sources("${CMAKE_CURRENT_SOURCE_DIR}/../glad.c")
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
diggler_link_libraries(dl)
endif()
endif()
if ("${DIGGLER_GL_LOADER}" STREQUAL "glbinding")
find_package(glbinding REQUIRED)
set(DIGGLER_GL_USE_GLAD TRUE)
set(DIGGLER_GL_LOADER_SUPPORTED TRUE)
diggler_add_definition("DIGGLER_GL_USE_GLBINDING")
diggler_include_directories(${glbinding_INCLUDE_DIRS})
diggler_link_libraries(glbinding)
endif()
if ("${DIGGLER_GL_LOADER}" STREQUAL "glew")
pkg_search_module(GLEW REQUIRED glew)
set(DIGGLER_GL_USE_GLEW TRUE)
set(DIGGLER_GL_LOADER_SUPPORTED TRUE)
diggler_add_definition("DIGGLER_GL_USE_GLEW")
diggler_include_directories(${GLEW_INCLUDE_DIRS})
diggler_link_libraries(${GLEW_LIBRARIES})
endif()
if (NOT DIGGLER_GL_LOADER_SUPPORTED)
message(SEND_ERROR "OpenGL loader \"${DIGGLER_GL_LOADER}\" is unsupported")
endif()
add_subdirectory("gl")
endif()
if(DIGGLER_ENABLE_VK_RENDERER)
if (DIGGLER_ENABLE_VK_RENDERER)
add_subdirectory("vk")
endif()

View File

@ -3,6 +3,8 @@ diggler_add_sources(
${CSD}/FBO.cpp
${CSD}/FeatureSupport.cpp
${CSD}/FontRenderer.cpp
${CSD}/OpenGL.cpp
${CSD}/OpenGL.${DIGGLER_GL_LOADER}.cpp
${CSD}/ParticlesRenderer.cpp
${CSD}/Program.cpp
${CSD}/ProgramManager.cpp

View File

@ -3,18 +3,6 @@
#include "FeatureSupport.hpp"
#include "Util.hpp"
#ifdef IN_IDE_PARSER
void glCheck();
#else
#define glCheck() { GLenum glErr = glGetError(); \
if (glErr) { \
getDebugStream() << getErrorString(glErr) << std::endl; \
} glErr = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (glErr != GL_FRAMEBUFFER_COMPLETE) { \
getDebugStream() << getErrorString(glErr) << std::endl; \
} \
}
#endif
namespace Diggler {
namespace Render {
namespace gl {
@ -34,8 +22,13 @@ FBO::FBO(int w, int h, Texture::PixelFormat format, bool stencil) : m_hasStencil
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
if (stencil) {
glRenderbufferStorage(GL_RENDERBUFFER, FeatureSupport::FBO_ARB ? GL_DEPTH24_STENCIL8 :
GL_DEPTH24_STENCIL8_OES, w, h);
#ifdef GL_DEPTH24_STENCIL8_OES
const GLenum depth24stencil8 = FeatureSupport::FBO_ARB ? GL_DEPTH24_STENCIL8 :
GL_DEPTH24_STENCIL8_OES;
#else
constexpr GLenum depth24stencil8 = GL_DEPTH24_STENCIL8;
#endif
glRenderbufferStorage(GL_RENDERBUFFER, depth24stencil8, w, h);
} else {
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, w, h);
}
@ -53,7 +46,14 @@ FBO::FBO(int w, int h, Texture::PixelFormat format, bool stencil) : m_hasStencil
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);
}
glCheck();
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR) {
getDebugStream() << getErrorString(glErr) << std::endl;
}
glErr = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (glErr != GL_FRAMEBUFFER_COMPLETE) {
getDebugStream() << getErrorString(glErr) << std::endl;
}
}
void FBO::resize(int w, int h) {

View File

@ -5,7 +5,7 @@
#include <vector>
#include <epoxy/gl.h>
#include "OpenGL.hpp"
#include "../../Texture.hpp"

View File

@ -2,6 +2,8 @@
#include <sstream>
#include "OpenGL.hpp"
namespace Diggler {
namespace Render {
namespace gl {
@ -18,14 +20,14 @@ bool
F::buffer_storage;
void F::probe() {
VAO = epoxy_has_gl_extension("GL_ARB_vertex_array_object") or
epoxy_has_gl_extension("GL_OES_vertex_array_object");
DSA_ARB = epoxy_has_gl_extension("GL_ARB_direct_state_access");
DSA_EXT = epoxy_has_gl_extension("GL_EXT_direct_state_access");
VAO = OpenGL::hasExtension("GL_ARB_vertex_array_object") or
OpenGL::hasExtension("GL_OES_vertex_array_object");
DSA_ARB = OpenGL::hasExtension("GL_ARB_direct_state_access");
DSA_EXT = OpenGL::hasExtension("GL_EXT_direct_state_access");
DSA = DSA_ARB or DSA_EXT;
shader_image_load_store = epoxy_has_gl_extension("GL_ARB_shader_image_load_store");
FBO_ARB = epoxy_has_gl_extension("GL_ARB_framebuffer_object");
buffer_storage = epoxy_has_gl_extension("GL_ARB_buffer_storage");
shader_image_load_store = OpenGL::hasExtension("GL_ARB_shader_image_load_store");
FBO_ARB = OpenGL::hasExtension("GL_ARB_framebuffer_object");
buffer_storage = OpenGL::hasExtension("GL_ARB_buffer_storage");
}
#define feature(x) if(x){oss<<#x<<std::endl;}

View File

@ -1,9 +1,7 @@
#ifndef DIGGLER_RENDER_GL_FEATURE_SUPPORT_HPP
#define DIGGLER_RENDER_GL_FEATURE_SUPPORT_HPP
#include "../../Platform.hpp"
#include <epoxy/gl.h>
#include "../../platform/Types.hpp"
namespace Diggler {
namespace Render {

40
src/render/gl/OpenGL.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "OpenGL.hpp"
#include <sstream>
namespace Diggler {
namespace Render {
namespace gl {
static std::set<std::string> extensionsSet;
void OpenGL::probeExtensions() {
if (version() >= 30) {
#ifdef GL_NUM_EXTENSIONS
GLint numExt;
glGetIntegerv(GL_NUM_EXTENSIONS, &numExt);
for (GLint i = 0; i < numExt; ++i) {
extensionsSet.insert(reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, GLuint(i))));
}
#endif
} else {
std::stringstream ss;
ss.str(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
std::string item;
while (std::getline(ss, item, ' ')) {
extensionsSet.insert(item);
}
}
}
const std::set<std::string>& OpenGL::extensions() {
return extensionsSet;
}
bool OpenGL::hasExtension(const std::string &ext) {
return extensionsSet.find(ext) != extensionsSet.end();
}
}
}
}

View File

@ -0,0 +1,51 @@
#include "OpenGL.hpp"
#include <stdexcept>
namespace Diggler {
namespace Render {
namespace gl {
void OpenGL::init() {
if (!gladLoadGL()) {
throw std::runtime_error("GLAD initialization failed");
}
probeExtensions();
}
std::set<OpenGL::Version> OpenGL::loaderSupportedGLVersions() {
return {};
}
OpenGL::Version OpenGL::version() {
const int major = GLVersion.major, minor = GLVersion.minor;
bool isForward = false;
#ifdef GL_CONTEXT_FLAGS
if (major >= 3) {
GLuint contextFlags;
glGetIntegerv(GL_CONTEXT_FLAGS, reinterpret_cast<GLint*>(&contextFlags));
isForward = bool(contextFlags & GLuint(GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT));
}
#endif
bool isCore = false;
#ifdef GL_CONTEXT_PROFILE_MASK
if (major >= 3 and (major >= 4 or minor >= 2)) {
GLuint profileFlags = 0;
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, reinterpret_cast<GLint*>(&profileFlags));
isCore = bool(profileFlags & GLuint(GL_CONTEXT_CORE_PROFILE_BIT));
}
#endif
return { major, minor, false, isCore, isForward };
}
const char* OpenGL::loaderName() {
return "GLAD";
}
const char* OpenGL::loaderVersion() {
return "rolling";
}
}
}
}

View File

@ -0,0 +1,58 @@
#include "OpenGL.hpp"
#include <glbinding/Binding.h>
#include <glbinding/ContextInfo.h>
#include <glbinding/Meta.h>
#include <glbinding/glbinding-version.h>
#include <glbinding/Version.h>
namespace Diggler {
namespace Render {
namespace gl {
void OpenGL::init() {
glbinding::Binding::initialize(false);
probeExtensions();
}
std::set<OpenGL::Version> OpenGL::loaderSupportedGLVersions() {
std::set<Version> versions;
for (const auto& version : glbinding::Meta::versions()) {
versions.emplace(version.majorVersion(), version.minorVersion(), false, false, false);
if (version.majorVersion() >= 3) {
versions.emplace(version.majorVersion(), version.minorVersion(), false, false, true);
versions.emplace(version.majorVersion(), version.minorVersion(), false, true, false);
versions.emplace(version.majorVersion(), version.minorVersion(), false, true, true);
}
}
return versions;
}
OpenGL::Version OpenGL::version() {
auto ver = glbinding::ContextInfo::version();
const int major = ver.majorVersion(), minor = ver.minorVersion();
GLuint contextFlags = 0;
if (major >= 3) {
glGetIntegerv(GL_CONTEXT_FLAGS, reinterpret_cast<GLint*>(&contextFlags));
}
GLuint profileFlags = 0;
if (major >= 3 and (major >= 4 or minor >= 2)) {
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, reinterpret_cast<GLint*>(&profileFlags));
}
return { major, minor, false,
bool(profileFlags & GLuint(GL_CONTEXT_CORE_PROFILE_BIT)),
bool(contextFlags & GLuint(GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
};
}
const char* OpenGL::loaderName() {
return "glbinding";
}
const char* OpenGL::loaderVersion() {
return GLBINDING_VERSION;
}
}
}
}

View File

@ -0,0 +1,58 @@
#include "OpenGL.hpp"
#include <stdexcept>
namespace Diggler {
namespace Render {
namespace gl {
void OpenGL::init() {
GLenum err = glewInit();
if (err != GLEW_OK) {
throw std::runtime_error(std::string("GLEW initialization failed") +
reinterpret_cast<const char*>(glewGetErrorString(err)));
}
probeExtensions();
}
std::set<OpenGL::Version> OpenGL::loaderSupportedGLVersions() {
std::set<Version> versions;
for (int ver : { 20, 21, 30, 31, 32, 33, 40, 41, 42, 43, 44, 45 }) {
versions.emplace(ver / 10, ver % 10, false, false, false);
if (ver >= 30) {
versions.emplace(ver / 10, ver % 10, false, false, true);
versions.emplace(ver / 10, ver % 10, false, true, false);
versions.emplace(ver / 10, ver % 10, false, true, true);
}
}
return versions;
}
OpenGL::Version OpenGL::version() {
auto ver = glGetString(GL_VERSION);
const int major = ver[0] - '0', minor = ver[2] - '0';
GLuint contextFlags = 0;
if (major >= 3) {
glGetIntegerv(GL_CONTEXT_FLAGS, reinterpret_cast<GLint*>(&contextFlags));
}
GLuint profileFlags = 0;
if (major >= 3 and (major >= 4 or minor >= 2)) {
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, reinterpret_cast<GLint*>(&profileFlags));
}
return { major, minor, false,
bool(profileFlags & GLuint(GL_CONTEXT_CORE_PROFILE_BIT)),
bool(contextFlags & GLuint(GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
};
}
const char* OpenGL::loaderName() {
return "GLEW";
}
const char* OpenGL::loaderVersion() {
return reinterpret_cast<const char*>(glewGetString(GLEW_VERSION));
}
}
}
}

95
src/render/gl/OpenGL.hpp Normal file
View File

@ -0,0 +1,95 @@
#ifndef DIGGLER_RENDER_GL_OPENGL_HPP
#define DIGGLER_RENDER_GL_OPENGL_HPP
#include "../../platform/Fixes.hpp"
#include <set>
#include <string>
#if defined(DIGGLER_GL_USE_LIBEPOXY)
#include <epoxy/gl.h>
#elif defined(DIGGLER_GL_USE_GLAD)
#include <glad/glad.h>
#elif defined(DIGGLER_GL_USE_GLBINDING)
#include <glbinding/gl/gl.h>
using namespace gl;
#elif defined(DIGGLER_GL_USE_GLEW)
#define GLEW_NO_GLU
#include <GL/glew.h>
#else
#error "No OpenGL loader selected"
#endif
namespace Diggler {
namespace Render {
namespace gl {
class OpenGL {
private:
static void probeExtensions();
public:
struct Version {
int major, minor;
bool isGLES, isCore, isForward;
Version(int major, int minor, bool isGLES, bool isCore, bool isForward) :
major(major),
minor(minor),
isGLES(isGLES),
isCore(isCore),
isForward(isForward) {}
operator int() const { return major * 10 + minor; }
bool operator<(const Version &v) const {
return major < v.major && minor < v.minor &&
(isGLES ^ v.isGLES) && (isCore ^ v.isCore) && (isForward ^ v.isForward);
}
};
/**
* @return The OpenGL Loader name
*/
static const char* loaderName();
/**
* @return The OpenGL Loader version
*/
static const char* loaderVersion();
/**
* Get the list of OpenGL versions whose initialization is supported by the Loader.
* An empty set means supported versions are unknown.
* @note Presence of a given version in this liss only shows Loader support, not driver support
* @return The OpenGL versions the Loader supports
*/
static std::set<Version> loaderSupportedGLVersions();
/**
* Initializes OpenGL entrypoints
*/
static void init();
/**
* @return The currently loaded OpenGL version
*/
static Version version();
/**
* @return The currently available OpenGL extensions
*/
static const std::set<std::string>& extensions();
/**
* Checks for availability of an OpenGL extension
* @return `true` if the extension is available, `false` otherwise
*/
static bool hasExtension(const std::string&);
};
}
}
}
#endif /* DIGGLER_RENDER_GL_OPENGL_HPP */

View File

@ -0,0 +1,57 @@
#include "OpenGL.hpp"
#include <array>
namespace Diggler {
namespace Render {
namespace gl {
void OpenGL::init() {
// libepoxy initializes lazily
probeExtensions();
}
std::set<OpenGL::Version> OpenGL::loaderSupportedGLVersions() {
std::set<Version> versions;
for (int ver : { 20, 21, 30, 31, 32, 33, 40, 41, 42, 43, 44, 45 }) {
versions.emplace(ver / 10, ver % 10, false, false, false);
if (ver >= 30) {
versions.emplace(ver / 10, ver % 10, false, false, true);
versions.emplace(ver / 10, ver % 10, false, true, false);
versions.emplace(ver / 10, ver % 10, false, true, true);
}
}
for (int ver : { 20, 30, 31, 32 }) {
versions.emplace(ver / 10, ver % 10, true, false, false);
}
return versions;
}
OpenGL::Version OpenGL::version() {
auto ver = epoxy_gl_version();
const int major = ver / 10, minor = ver % 10;
GLuint contextFlags = 0;
if (major >= 3) {
glGetIntegerv(GL_CONTEXT_FLAGS, reinterpret_cast<GLint*>(&contextFlags));
}
GLuint profileFlags = 0;
if (major >= 3 and (major >= 4 or minor >= 2)) {
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, reinterpret_cast<GLint*>(&profileFlags));
}
return { major, minor, !epoxy_is_desktop_gl(),
bool(profileFlags & GL_CONTEXT_CORE_PROFILE_BIT),
bool(contextFlags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
};
}
const char* OpenGL::loaderName() {
return "libepoxy";
}
const char* OpenGL::loaderVersion() {
return "rolling";
}
}
}
}

View File

@ -8,7 +8,11 @@ namespace Diggler {
namespace Render {
namespace gl {
Program::Program(Shader* vsh, Shader* fsh) : vsh(vsh), fsh(fsh), id(0) {
Program::Program(Shader* vsh, Shader* fsh) :
vsh(vsh),
fsh(fsh),
id(0),
linked(GL_FALSE) {
}
@ -34,7 +38,9 @@ bool Program::link() {
glAttachShader(id, vsh->getId());
glAttachShader(id, fsh->getId());
glLinkProgram(id);
glGetProgramiv(id, GL_LINK_STATUS, &linked);
GLint linkStatus;
glGetProgramiv(id, GL_LINK_STATUS, &linkStatus);
linked = GLboolean(linkStatus);
if (!linked) {
getErrorStream() << id << ':' << getError() << std::endl;
return false;

View File

@ -11,7 +11,7 @@ class Program {
private:
Shader *vsh, *fsh;
GLuint id;
GLint linked = GL_FALSE;
GLboolean linked;
bool mustDestroy = false;
std::string fshPath, vshPath;

View File

@ -0,0 +1,25 @@
# Using GLAD in Diggler
GLAD is a small, generated OpenGL loader targeting a single GL version with an optional set of supported extensions.
It is hosted on GitHub at https://github.com/Dav1dde/glad . It can be either installed, or [used from a web service](http://glad.dav1d.de/).
## Diggler requirements
Diggler mandates a minimum support of OpenGL (ES) 2.0.
On desktop OpenGL, loader support of these extensions is required:
* GL_ARB_buffer_storage
* GL_ARB_direct_state_access
* GL_ARB_framebuffer_object
* GL_ARB_shader_image_load_store
* GL_ARB_vertex_array_object
* GL_EXT_direct_state_access
* GL_KHR_debug
```
--profile="compatibility" --api="gl=2.0" --generator="c" --spec="gl" --extensions="GL_ARB_buffer_storage,GL_ARB_direct_state_access,GL_ARB_framebuffer_object,GL_ARB_shader_image_load_store,GL_ARB_vertex_array_object,GL_EXT_direct_state_access,GL_KHR_debug"
```
As said, you can [generate the loader online](http://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D2.0&extensions=GL_ARB_buffer_storage&extensions=GL_ARB_direct_state_access&extensions=GL_ARB_framebuffer_object&extensions=GL_ARB_shader_image_load_store&extensions=GL_ARB_vertex_array_object&extensions=GL_EXT_direct_state_access&extensions=GL_KHR_debug).

View File

@ -51,8 +51,9 @@ bool Shader::compileFromString(const std::string &source, const std::string &pat
const char *src = srcStr.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
GLint compiled;
glGetShaderiv(id, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
if (!GLboolean(compiled)) {
getErrorStream() << "Compile error in " << path << "\n" << getError() << std::endl;
return false;
}

View File

@ -4,7 +4,7 @@
#include <string>
#include <vector>
#include <epoxy/gl.h>
#include "OpenGL.hpp"
namespace Diggler {
namespace Render {
@ -13,13 +13,12 @@ namespace gl {
class Shader {
private:
GLuint id;
GLint compiled = GL_FALSE;
const std::vector<std::string> *m_preludeLines;
public:
enum class Type : GLenum {
FRAGMENT = GL_FRAGMENT_SHADER,
VERTEX = GL_VERTEX_SHADER
enum class Type : unsigned int {
FRAGMENT = static_cast<unsigned int>(GL_FRAGMENT_SHADER),
VERTEX = static_cast<unsigned int>(GL_VERTEX_SHADER)
} type;
Shader(Type type);
Shader(Type type, const std::string& path);

View File

@ -22,8 +22,10 @@ const char* getErrorString(GLenum code) {
return "GL_OUT_OF_MEMORY";
case GL_INVALID_FRAMEBUFFER_OPERATION:
return "GL_INVALID_FRAMEBUFFER_OPERATION";
#ifdef GL_TABLE_TOO_LARGE
case GL_TABLE_TOO_LARGE:
return "GL_TABLE_TOO_LARGE";
#endif
case GL_FRAMEBUFFER_COMPLETE:
return "GL_FRAMEBUFFER_COMPLETE";
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
@ -36,6 +38,8 @@ const char* getErrorString(GLenum code) {
return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
case GL_FRAMEBUFFER_UNSUPPORTED:
return "GL_FRAMEBUFFER_UNSUPPORTED";
default:
break;
}
return "";
}

View File

@ -3,7 +3,7 @@
#include "../../Platform.hpp"
#include <epoxy/gl.h>
#include "OpenGL.hpp"
namespace Diggler {
namespace Render {
@ -43,8 +43,10 @@ constexpr GLenum getBinding(GLenum bufferT) {
return GL_RENDERBUFFER_BINDING;
case GL_VERTEX_ARRAY:
return GL_VERTEX_ARRAY_BINDING;
default:
break;
}
return 0;
return GL_INVALID_ENUM;
}
template<GLenum BufferT, GLenum BoundBufferT = getBinding(BufferT)>

View File

@ -5,7 +5,7 @@
#include <vector>
#include <epoxy/gl.h>
#include "OpenGL.hpp"
#include "FeatureSupport.hpp"
#include "Util.hpp"

View File

@ -3,7 +3,7 @@
#include <vector>
#include <epoxy/gl.h>
#include "OpenGL.hpp"
#include "../../platform/PreprocUtils.hpp"
#include "FeatureSupport.hpp"

View File

@ -3,7 +3,7 @@
#include "../Platform.hpp"
#include <epoxy/gl.h>
#include "../render/gl/OpenGL.hpp"
#include <glm/glm.hpp>
#include "../render/FontRendererFwd.hpp"