Make use of (and require) OpenGL 4.x features present in mesa 11.0+

This commit is contained in:
2015-10-08 14:31:57 +02:00
parent a9b339019b
commit e297b21762
11 changed files with 93 additions and 102 deletions

View File

@@ -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);

View File

@@ -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<TexAtlasInfo> atlasInfo;
if (texs.size() > 0) {
std::tie(atlasInfo, tex_) = genTexAtlas(texs, usedTexs, palt.getPalette());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, static_cast<int>(GL_LINEAR_MIPMAP_LINEAR));
glTextureParameteri(tex_, GL_TEXTURE_MIN_FILTER, static_cast<int>(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<int>(GL_LINEAR_MIPMAP_LINEAR));
glTextureParameteri(texAnim_, GL_TEXTURE_MIN_FILTER, static_cast<int>(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());
glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId());
glBindVertexArray(vertexArray_);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_.getVBOId());
glVertexArrayVertexBuffer(vertexArray_, 0, vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs));
glVertexArrayElementBuffer(vertexArray_, vbo_.getVBOId());
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_, 0);
glVertexArrayAttribFormat(vertexArray_, 0, 3, GL_INT, GL_FALSE, offsetof(VertexAttribs, vertex));
glVertexArrayAttribBinding(vertexArray_, 0, 0);
glBufferSubData(GL_ARRAY_BUFFER, vbo_.getBase(),
glEnableVertexArrayAttrib(vertexArray_, 1);
glVertexArrayAttribFormat(vertexArray_, 1, 2, GL_UNSIGNED_SHORT, GL_TRUE, offsetof(VertexAttribs, texCoords));
glVertexArrayAttribBinding(vertexArray_, 1, 0);
glEnableVertexArrayAttrib(vertexArray_, 2);
glVertexArrayAttribIFormat(vertexArray_, 2, 1, GL_UNSIGNED_BYTE, offsetof(VertexAttribs, useTexAnim));
glVertexArrayAttribBinding(vertexArray_, 2, 0);
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<GLuint, 2> texs{tex_, texAnim_};
glBindTextures(0, 2, texs.data());
} else
glBindTextures(0, 1, &tex_.get());
glBindVertexArray(vertexArray_);

View File

@@ -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<int>(GL_LINEAR));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<int>(GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast<int>(GL_CLAMP_TO_EDGE));
glTextureParameteri(texture_, GL_TEXTURE_MAG_FILTER, static_cast<int>(GL_NEAREST));
glTextureParameteri(texture_, GL_TEXTURE_WRAP_S, static_cast<int>(GL_CLAMP_TO_EDGE));
glTextureParameteri(texture_, GL_TEXTURE_WRAP_T, static_cast<int>(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> vertexAttribs{
{{l, t}, {0, 0}},
@@ -36,19 +36,17 @@ namespace render {
{{l, b}, {0, 65535u}},
{{r, b}, {65535u, 65535u}}};
glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId());
glBindVertexArray(vertexArray_);
glVertexArrayVertexBuffer(vertexArray_, 0, vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs));
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)));
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);
glBufferSubData(GL_ARRAY_BUFFER, vbo_.getBase(),
sizeof(VertexAttribs)*6,
vertexAttribs.data());
glNamedBufferSubData(vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs)*6,
vertexAttribs.data());
ovlProj_ = glm::ortho(0.0f, static_cast<float>(renderer_.getWidth()),
static_cast<float>(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);
}
}

View File

@@ -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);

View File

@@ -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_);

View File

@@ -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});
}

View File

@@ -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<gl::GLenum, std::vector<VBO> > _vbos;
std::vector<VBO> _vbos;
};
}

View File

@@ -55,26 +55,16 @@ namespace render {
TextureResource create2DTexture(unsigned width, unsigned height, bool alpha, unsigned levels)
{
TextureResource tex;
glGenTextures(1, &tex.get());
glCreateTextures(GL_TEXTURE_2D, 1, &tex.get());
glBindTexture(GL_TEXTURE_2D, tex);
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<const int>(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<const int>(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;
}