diff --git a/shaders/object.fs b/shaders/object.frag similarity index 81% rename from shaders/object.fs rename to shaders/object.frag index 6f98a7d..def4bbe 100644 --- a/shaders/object.fs +++ b/shaders/object.frag @@ -1,6 +1,9 @@ #version 330 core #extension GL_ARB_explicit_uniform_location : enable +#extension GL_ARB_shading_language_420pack : enable +#ifdef GL_ARB_conservative_depth #extension GL_ARB_conservative_depth : enable +#endif layout(location = 2) uniform sampler2D texBase; layout(location = 3) uniform sampler2DArray texAnim; @@ -11,7 +14,9 @@ in vec2 fragTC; flat in uint fragUseAnimTex; layout(location = 0) out vec4 color; +#ifdef GL_ARB_conservative_depth layout(depth_unchanged) out float gl_FragDepth; +#endif void main(void) { vec4 texel = bool(fragUseAnimTex)?texture(texAnim, vec3(fragTC, animFrame)):texture(texBase, fragTC); diff --git a/shaders/object.vs b/shaders/object.vert similarity index 100% rename from shaders/object.vs rename to shaders/object.vert diff --git a/shaders/overlay.fs b/shaders/overlay.frag similarity index 100% rename from shaders/overlay.fs rename to shaders/overlay.frag diff --git a/shaders/overlay.vs b/shaders/overlay.vert similarity index 100% rename from shaders/overlay.vs rename to shaders/overlay.vert diff --git a/src/render/Object.cc b/src/render/Object.cc index 5da9e96..180f0e0 100644 --- a/src/render/Object.cc +++ b/src/render/Object.cc @@ -44,7 +44,7 @@ namespace render { /* Copy from paletted texture 'src' into BGRA texture 'dst' using palette 'palt' Palette entry 0xff is transparent, all others are opaque. - For opaque pixels the color components are copied from a neighbouring + For transparent pixels the color components are copied from a neighbouring opaque pixel if available. */ void copyPaletteTexture(uint8_t const* src, unsigned srcWidth, unsigned srcHeight, @@ -301,14 +301,14 @@ namespace render { atlasWidth*4, palt); } - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, atlasWidth, atlasHeight, GL_BGRA, GL_UNSIGNED_BYTE, pixels.data()); + glTextureSubImage2D(tex, 0, 0, 0, atlasWidth, atlasHeight, GL_BGRA, GL_UNSIGNED_BYTE, pixels.data()); auto mipdata = genMipmap(pixels.data(), atlasWidth, atlasHeight, minLg); size_t pos = 0; for (unsigned lvl = 1;lvl <= minLg;++lvl) { unsigned lWidth = std::max(atlasWidth>>lvl, 1u), lHeight = std::max(atlasHeight>>lvl, 1u); - glTexSubImage2D(GL_TEXTURE_2D, lvl, 0, 0, lWidth, lHeight, - GL_BGRA, GL_UNSIGNED_BYTE, mipdata.data()+pos); + glTextureSubImage2D(tex, lvl, 0, 0, lWidth, lHeight, + GL_BGRA, GL_UNSIGNED_BYTE, mipdata.data()+pos); pos += lWidth*lHeight*4; } @@ -344,8 +344,8 @@ namespace render { pixels.data()+f*width*height*4, width*4, palt); } - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, texAnim.frames, - GL_BGRA, GL_UNSIGNED_BYTE, pixels.data()); + glTextureSubImage3D(tex, 0, 0, 0, 0, width, height, texAnim.frames, + GL_BGRA, GL_UNSIGNED_BYTE, pixels.data()); unsigned logWidth = ilog2(width), logHeight = ilog2(height); unsigned levels = std::max(logWidth, logHeight); for (unsigned f = 0;f < texAnim.frames;++f) { @@ -355,8 +355,8 @@ namespace render { unsigned lWidth = std::max(width>>lvl, 1u), lHeight = std::max(height>>lvl, 1u); - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, lvl, 0, 0, f, lWidth, lHeight, 1, - GL_BGRA, GL_UNSIGNED_BYTE, mipdata.data()+pos); + glTextureSubImage3D(tex, lvl, 0, 0, f, lWidth, lHeight, 1, + GL_BGRA, GL_UNSIGNED_BYTE, mipdata.data()+pos); pos += lWidth*lHeight*4; } } @@ -481,14 +481,14 @@ namespace render { std::vector atlasInfo; if (texs.size() > 0) { std::tie(atlasInfo, tex_) = genTexAtlas(texs, usedTexs, palt.getPalette()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, static_cast(GL_LINEAR_MIPMAP_LINEAR)); + glTextureParameteri(tex_, GL_TEXTURE_MIN_FILTER, static_cast(GL_LINEAR_MIPMAP_LINEAR)); } auto& texAnims = obj.getTextureAnimations(); AnimTexInfo animInfo; if ((usedTexs.find(atlasInfo.size()) != usedTexs.end()) && (texAnims.size() > 0)) { std::tie(animInfo, texAnim_) = genTexAnim(texAnims[0], palt.getPalette()); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, static_cast(GL_LINEAR_MIPMAP_LINEAR)); + glTextureParameteri(texAnim_, GL_TEXTURE_MIN_FILTER, static_cast(GL_LINEAR_MIPMAP_LINEAR)); } // Generate vertex attribute array @@ -500,25 +500,26 @@ namespace render { std::tie(vertexAttribs, indices) = genVertexAttribs(obj, tris, quads, atlasInfo); // Setup GL vertex buffer and vertex array - glGenVertexArrays(1, &vertexArray_.get()); + glCreateVertexArrays(1, &vertexArray_.get()); vbo_ = VBOManager::getInstance().alloc(sizeof(VertexAttribs)*vertexAttribs.size()+ 2*indices.size()); + + glVertexArrayVertexBuffer(vertexArray_, 0, vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs)); + glVertexArrayElementBuffer(vertexArray_, vbo_.getVBOId()); - glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId()); - glBindVertexArray(vertexArray_); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_.getVBOId()); + glEnableVertexArrayAttrib(vertexArray_, 0); + glVertexArrayAttribFormat(vertexArray_, 0, 3, GL_INT, GL_FALSE, offsetof(VertexAttribs, vertex)); + glVertexArrayAttribBinding(vertexArray_, 0, 0); + + glEnableVertexArrayAttrib(vertexArray_, 1); + glVertexArrayAttribFormat(vertexArray_, 1, 2, GL_UNSIGNED_SHORT, GL_TRUE, offsetof(VertexAttribs, texCoords)); + glVertexArrayAttribBinding(vertexArray_, 1, 0); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_INT, GL_FALSE, sizeof(VertexAttribs), - vbo_.getOfs(offsetof(VertexAttribs, vertex))); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(VertexAttribs), - vbo_.getOfs(offsetof(VertexAttribs, texCoords))); - glEnableVertexAttribArray(2); - glVertexAttribIPointer(2, 1, GL_UNSIGNED_BYTE, sizeof(VertexAttribs), - vbo_.getOfs(offsetof(VertexAttribs, useTexAnim))); + glEnableVertexArrayAttrib(vertexArray_, 2); + glVertexArrayAttribIFormat(vertexArray_, 2, 1, GL_UNSIGNED_BYTE, offsetof(VertexAttribs, useTexAnim)); + glVertexArrayAttribBinding(vertexArray_, 2, 0); - glBufferSubData(GL_ARRAY_BUFFER, vbo_.getBase(), + glNamedBufferSubData(vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs)*vertexAttribs.size(), vertexAttribs.data()); @@ -526,7 +527,7 @@ namespace render { indexOfs_ = sizeof(VertexAttribs)*vertexAttribs.size(); numIndices_ = indices.size(); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, vbo_.getBase()+indexOfs_, + glNamedBufferSubData(vbo_.getVBOId(), vbo_.getBase()+indexOfs_, 2*numIndices_, indices.data()); @@ -560,13 +561,13 @@ namespace render { glUniform1i(2, 0); glUniform1i(3, 1); - glBindTexture(GL_TEXTURE_2D, tex_); if (texAnim_) { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D_ARRAY, texAnim_); - glActiveTexture(GL_TEXTURE0); glUniform1ui(4, animFrame_); - } + + std::array texs{tex_, texAnim_}; + glBindTextures(0, 2, texs.data()); + } else + glBindTextures(0, 1, &tex_.get()); glBindVertexArray(vertexArray_); diff --git a/src/render/Overlay.cc b/src/render/Overlay.cc index 350310e..0100a9f 100644 --- a/src/render/Overlay.cc +++ b/src/render/Overlay.cc @@ -21,12 +21,12 @@ namespace render { vbo_(VBOManager::getInstance().alloc(sizeof(VertexAttribs)*6)), width_(width), height_(height), top_(top), left_(left), intWidth_(intWidth), intHeight_(intHeight) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, static_cast(GL_LINEAR)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast(GL_CLAMP_TO_EDGE)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast(GL_CLAMP_TO_EDGE)); + glTextureParameteri(texture_, GL_TEXTURE_MAG_FILTER, static_cast(GL_NEAREST)); + glTextureParameteri(texture_, GL_TEXTURE_WRAP_S, static_cast(GL_CLAMP_TO_EDGE)); + glTextureParameteri(texture_, GL_TEXTURE_WRAP_T, static_cast(GL_CLAMP_TO_EDGE)); program_ = ProgramProvider::getInstance().getProgram("overlay", "overlay"); - glGenVertexArrays(1, &vertexArray_.get()); + glCreateVertexArrays(1, &vertexArray_.get()); short int t = top_, l = left_, b = height+top_, r = width+left_; std::vector vertexAttribs{ {{l, t}, {0, 0}}, @@ -35,21 +35,19 @@ namespace render { {{l, t}, {0, 0}}, {{l, b}, {0, 65535u}}, {{r, b}, {65535u, 65535u}}}; + + glVertexArrayVertexBuffer(vertexArray_, 0, vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs)); - glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId()); - glBindVertexArray(vertexArray_); - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE, sizeof(VertexAttribs), - vbo_.getOfs(offsetof(VertexAttribs, vertex))); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(VertexAttribs), - vbo_.getOfs(offsetof(VertexAttribs, texCoords))); - - glBufferSubData(GL_ARRAY_BUFFER, vbo_.getBase(), - sizeof(VertexAttribs)*6, - vertexAttribs.data()); + glEnableVertexArrayAttrib(vertexArray_, 0); + glVertexArrayAttribFormat(vertexArray_, 0, 2, GL_SHORT, GL_FALSE, offsetof(VertexAttribs, vertex)); + glVertexArrayAttribBinding(vertexArray_, 0, 0); + glEnableVertexArrayAttrib(vertexArray_, 1); + glVertexArrayAttribFormat(vertexArray_, 1, 2, GL_UNSIGNED_SHORT, GL_TRUE, offsetof(VertexAttribs, texCoords)); + glVertexArrayAttribBinding(vertexArray_, 1, 0); + glNamedBufferSubData(vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs)*6, + vertexAttribs.data()); + ovlProj_ = glm::ortho(0.0f, static_cast(renderer_.getWidth()), static_cast(renderer_.getHeight()), 0.0f); } @@ -84,27 +82,23 @@ namespace render { (content->w > intWidth_)) throw Exception{"null or mismatched surface"}; - glBindTexture(GL_TEXTURE_2D, texture_); - if (content->format->format != SDL_PIXELFORMAT_ARGB8888) { printf("Warning: Format conversion in Overlay::setContent\n"); SDLSurfaceUPtr tmpSurf(SDL_ConvertSurfaceFormat(content, SDL_PIXELFORMAT_ARGB8888, 0)); if (!tmpSurf) throw SDLException{}; - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tmpSurf->w, tmpSurf->h, GL_BGRA, GL_UNSIGNED_BYTE, tmpSurf->pixels); + glTextureSubImage2D(texture_, 0, 0, 0, tmpSurf->w, tmpSurf->h, GL_BGRA, GL_UNSIGNED_BYTE, tmpSurf->pixels); } else - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, content->w, content->h, GL_BGRA, GL_UNSIGNED_BYTE, content->pixels); + glTextureSubImage2D(texture_, 0, 0, 0, content->w, content->h, GL_BGRA, GL_UNSIGNED_BYTE, content->pixels); } void Overlay::setContentRGB8(void *data) { - glBindTexture(GL_TEXTURE_2D, texture_); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, intWidth_, intHeight_, GL_RGB, GL_UNSIGNED_BYTE, data); + glTextureSubImage2D(texture_, 0, 0, 0, intWidth_, intHeight_, GL_RGB, GL_UNSIGNED_BYTE, data); } void Overlay::setContentBGRA8(void *data) { - glBindTexture(GL_TEXTURE_2D, texture_); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, intWidth_, intHeight_, GL_BGRA, GL_UNSIGNED_BYTE, data); + glTextureSubImage2D(texture_, 0, 0, 0, intWidth_, intHeight_, GL_BGRA, GL_UNSIGNED_BYTE, data); } } diff --git a/src/render/ProgramProvider.cc b/src/render/ProgramProvider.cc index b1d4bd1..11d70d6 100644 --- a/src/render/ProgramProvider.cc +++ b/src/render/ProgramProvider.cc @@ -64,8 +64,8 @@ namespace render { ShaderResource vs(glCreateShader(GL_VERTEX_SHADER)), fs(glCreateShader(GL_FRAGMENT_SHADER)); - shaderCompile_(vertexShader + ".vs", vs); - shaderCompile_(fragShader + ".fs", fs); + shaderCompile_(vertexShader + ".vert", vs); + shaderCompile_(fragShader + ".frag", fs); ProgramResource prog(glCreateProgram()); glAttachShader(prog, vs); diff --git a/src/render/Renderer.cc b/src/render/Renderer.cc index 1b906f7..301b4ea 100644 --- a/src/render/Renderer.cc +++ b/src/render/Renderer.cc @@ -56,13 +56,15 @@ namespace render { } + void requireExtension(std::string const& extname) { + bool support = SDL_GL_ExtensionSupported(extname.c_str()); + if (!support) + throw Exception("Required OpenGL extension " + extname + " not found"); + } Renderer::Renderer(bool fullscreen) : sdlInit_(), ttfInit_(), window_(), context_() { - // Initialize OpenGL - glbinding::Binding::initialize(); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); @@ -79,6 +81,9 @@ namespace render { context_ = SDLGLContext(window_.get()); + // Initialize OpenGL + glbinding::Binding::initialize(); + SDL_GetWindowSize(window_.get(), &width_, &height_); glbinding::setCallbackMask(glbinding::CallbackMask::After); @@ -95,6 +100,14 @@ namespace render { } #endif + // All commercial GL implementations, and all mesa versions >= 11.0, should provide these + requireExtension("GL_ARB_texture_storage"); + requireExtension("GL_ARB_buffer_storage"); + requireExtension("GL_ARB_direct_state_access"); + requireExtension("GL_ARB_shading_language_420pack"); + requireExtension("GL_ARB_explicit_uniform_location"); + requireExtension("GL_ARB_multi_bind"); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glViewport(0, 0, width_, height_); diff --git a/src/render/VBOManager.cc b/src/render/VBOManager.cc index 3e3a113..c0a3f01 100644 --- a/src/render/VBOManager.cc +++ b/src/render/VBOManager.cc @@ -52,9 +52,9 @@ namespace render { { } - VBOManager::VBOAlloc VBOManager::alloc(size_t size, GLenum type) + VBOManager::VBOAlloc VBOManager::alloc(size_t size) { - for(auto& vbo : _vbos[type]) { + for(auto& vbo : _vbos) { try { return vbo.alloc(size); } catch (AllocFailed &ex) { @@ -62,17 +62,17 @@ namespace render { } } - _vbos[type].emplace_back((size>default_size)?size:default_size, type); + _vbos.emplace_back((size>default_size)?size:default_size); - return _vbos[type].back().alloc(size); + return _vbos.back().alloc(size); } - VBOManager::VBO::VBO(size_t size, GLenum type) + VBOManager::VBO::VBO(size_t size) : _bufID(0) { - glGenBuffers(1, &_bufID); - glBindBuffer(GL_ARRAY_BUFFER, _bufID); - glBufferData(GL_ARRAY_BUFFER, size, NULL, type); + glCreateBuffers(1, &_bufID); + glNamedBufferStorage(_bufID, size, NULL, GL_DYNAMIC_STORAGE_BIT); + _allocs.emplace_back(_Entry{size, false}); } diff --git a/src/render/VBOManager.hh b/src/render/VBOManager.hh index 2122543..be8d54e 100644 --- a/src/render/VBOManager.hh +++ b/src/render/VBOManager.hh @@ -19,7 +19,6 @@ namespace render { static const size_t default_size; static const size_t alignment = 4; - static const gl::GLenum default_type = gl::GL_STATIC_DRAW; class AllocFailed {}; @@ -72,13 +71,13 @@ namespace render { size_t _ofs, _size; }; - VBOAlloc alloc(size_t size, gl::GLenum type = default_type); + VBOAlloc alloc(size_t size); private: class VBO { public: - VBO(size_t size = default_size, gl::GLenum type = default_type); + VBO(size_t size = default_size); VBO(VBO const& copy) = delete; VBO& operator=(VBO const& copy) = delete; @@ -108,7 +107,7 @@ namespace render { }; - std::map > _vbos; + std::vector _vbos; }; } diff --git a/src/render/renderutil.cc b/src/render/renderutil.cc index 323685f..3eff666 100644 --- a/src/render/renderutil.cc +++ b/src/render/renderutil.cc @@ -55,26 +55,16 @@ namespace render { TextureResource create2DTexture(unsigned width, unsigned height, bool alpha, unsigned levels) { TextureResource tex; - glGenTextures(1, &tex.get()); - - glBindTexture(GL_TEXTURE_2D, tex); + glCreateTextures(GL_TEXTURE_2D, 1, &tex.get()); + unsigned logWidth = ilog2(width), logHeight = ilog2(height); if (levels == 0) levels = std::max(logWidth,logHeight)+1u; - if(extensionSupported("GL_ARB_texture_storage")) - glTexStorage2D(GL_TEXTURE_2D, levels, alpha?GL_RGBA8:GL_RGB8, width, height); - else { - std::printf("Warning: extension GL_ARB_texture_storage not supported!\n"); - for (unsigned i = 0u; i < levels; ++i) { - glTexImage2D(GL_TEXTURE_2D, i, static_cast(alpha?GL_RGBA8:GL_RGB8), width, height, 0, - alpha?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, NULL); - width = std::max(1u, (width / 2u)); - height = std::max(1u, (height / 2u)); - } - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels-1); + glTextureStorage2D(tex, levels, alpha?GL_RGBA8:GL_RGB8, width, height); + + glTextureParameteri(tex, GL_TEXTURE_MAX_LEVEL, levels-1); return tex; } @@ -83,27 +73,16 @@ namespace render { bool alpha, unsigned levels) { TextureResource tex; - glGenTextures(1, &tex.get()); + glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &tex.get()); - glBindTexture(GL_TEXTURE_2D_ARRAY, tex); unsigned logWidth = ilog2(width), logHeight = ilog2(height); if (levels == 0) levels = std::max(logWidth,logHeight)+1u; - if(extensionSupported("GL_ARB_texture_storage")) - glTexStorage3D(GL_TEXTURE_2D_ARRAY, levels, alpha?GL_RGBA8:GL_RGB8, width, height, count); - else { - std::printf("Warning: extension GL_ARB_texture_storage not supported!\n"); - for (unsigned i = 0u; i < levels; ++i) { - glTexImage3D(GL_TEXTURE_2D_ARRAY, i, static_cast(alpha?GL_RGBA8:GL_RGB8), - width, height, count, - 0, alpha?GL_RGBA8:GL_RGB8, GL_UNSIGNED_BYTE, NULL); - width = std::max(1u, (width / 2u)); - height = std::max(1u, (height / 2u)); - } - } - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, levels-1); + glTextureStorage3D(tex, levels, alpha?GL_RGBA8:GL_RGB8, width, height, count); + + glTextureParameteri(tex, GL_TEXTURE_MAX_LEVEL, levels-1); return tex; }