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 #version 330 core
#extension GL_ARB_explicit_uniform_location : enable #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 #extension GL_ARB_conservative_depth : enable
#endif
layout(location = 2) uniform sampler2D texBase; layout(location = 2) uniform sampler2D texBase;
layout(location = 3) uniform sampler2DArray texAnim; layout(location = 3) uniform sampler2DArray texAnim;
@@ -11,7 +14,9 @@ in vec2 fragTC;
flat in uint fragUseAnimTex; flat in uint fragUseAnimTex;
layout(location = 0) out vec4 color; layout(location = 0) out vec4 color;
#ifdef GL_ARB_conservative_depth
layout(depth_unchanged) out float gl_FragDepth; layout(depth_unchanged) out float gl_FragDepth;
#endif
void main(void) { void main(void) {
vec4 texel = bool(fragUseAnimTex)?texture(texAnim, vec3(fragTC, animFrame)):texture(texBase, fragTC); 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' /* Copy from paletted texture 'src' into BGRA texture 'dst' using palette 'palt'
Palette entry 0xff is transparent, all others are opaque. 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. opaque pixel if available.
*/ */
void copyPaletteTexture(uint8_t const* src, unsigned srcWidth, unsigned srcHeight, void copyPaletteTexture(uint8_t const* src, unsigned srcWidth, unsigned srcHeight,
@@ -301,14 +301,14 @@ namespace render {
atlasWidth*4, atlasWidth*4,
palt); 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); auto mipdata = genMipmap(pixels.data(), atlasWidth, atlasHeight, minLg);
size_t pos = 0; size_t pos = 0;
for (unsigned lvl = 1;lvl <= minLg;++lvl) { for (unsigned lvl = 1;lvl <= minLg;++lvl) {
unsigned lWidth = std::max(atlasWidth>>lvl, 1u), unsigned lWidth = std::max(atlasWidth>>lvl, 1u),
lHeight = std::max(atlasHeight>>lvl, 1u); lHeight = std::max(atlasHeight>>lvl, 1u);
glTexSubImage2D(GL_TEXTURE_2D, lvl, 0, 0, lWidth, lHeight, glTextureSubImage2D(tex, lvl, 0, 0, lWidth, lHeight,
GL_BGRA, GL_UNSIGNED_BYTE, mipdata.data()+pos); GL_BGRA, GL_UNSIGNED_BYTE, mipdata.data()+pos);
pos += lWidth*lHeight*4; pos += lWidth*lHeight*4;
} }
@@ -344,8 +344,8 @@ namespace render {
pixels.data()+f*width*height*4, width*4, pixels.data()+f*width*height*4, width*4,
palt); palt);
} }
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, texAnim.frames, glTextureSubImage3D(tex, 0, 0, 0, 0, width, height, texAnim.frames,
GL_BGRA, GL_UNSIGNED_BYTE, pixels.data()); GL_BGRA, GL_UNSIGNED_BYTE, pixels.data());
unsigned logWidth = ilog2(width), logHeight = ilog2(height); unsigned logWidth = ilog2(width), logHeight = ilog2(height);
unsigned levels = std::max(logWidth, logHeight); unsigned levels = std::max(logWidth, logHeight);
for (unsigned f = 0;f < texAnim.frames;++f) { for (unsigned f = 0;f < texAnim.frames;++f) {
@@ -355,8 +355,8 @@ namespace render {
unsigned lWidth = std::max(width>>lvl, 1u), unsigned lWidth = std::max(width>>lvl, 1u),
lHeight = std::max(height>>lvl, 1u); lHeight = std::max(height>>lvl, 1u);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, lvl, 0, 0, f, lWidth, lHeight, 1, glTextureSubImage3D(tex, lvl, 0, 0, f, lWidth, lHeight, 1,
GL_BGRA, GL_UNSIGNED_BYTE, mipdata.data()+pos); GL_BGRA, GL_UNSIGNED_BYTE, mipdata.data()+pos);
pos += lWidth*lHeight*4; pos += lWidth*lHeight*4;
} }
} }
@@ -481,14 +481,14 @@ namespace render {
std::vector<TexAtlasInfo> atlasInfo; std::vector<TexAtlasInfo> atlasInfo;
if (texs.size() > 0) { if (texs.size() > 0) {
std::tie(atlasInfo, tex_) = genTexAtlas(texs, usedTexs, palt.getPalette()); 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(); auto& texAnims = obj.getTextureAnimations();
AnimTexInfo animInfo; AnimTexInfo animInfo;
if ((usedTexs.find(atlasInfo.size()) != usedTexs.end()) && (texAnims.size() > 0)) { if ((usedTexs.find(atlasInfo.size()) != usedTexs.end()) && (texAnims.size() > 0)) {
std::tie(animInfo, texAnim_) = genTexAnim(texAnims[0], palt.getPalette()); 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 // Generate vertex attribute array
@@ -500,25 +500,26 @@ namespace render {
std::tie(vertexAttribs, indices) = genVertexAttribs(obj, tris, quads, atlasInfo); std::tie(vertexAttribs, indices) = genVertexAttribs(obj, tris, quads, atlasInfo);
// Setup GL vertex buffer and vertex array // Setup GL vertex buffer and vertex array
glGenVertexArrays(1, &vertexArray_.get()); glCreateVertexArrays(1, &vertexArray_.get());
vbo_ = VBOManager::getInstance().alloc(sizeof(VertexAttribs)*vertexAttribs.size()+ vbo_ = VBOManager::getInstance().alloc(sizeof(VertexAttribs)*vertexAttribs.size()+
2*indices.size()); 2*indices.size());
glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId()); glVertexArrayVertexBuffer(vertexArray_, 0, vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs));
glBindVertexArray(vertexArray_); glVertexArrayElementBuffer(vertexArray_, vbo_.getVBOId());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_.getVBOId());
glEnableVertexAttribArray(0); glEnableVertexArrayAttrib(vertexArray_, 0);
glVertexAttribPointer(0, 3, GL_INT, GL_FALSE, sizeof(VertexAttribs), glVertexArrayAttribFormat(vertexArray_, 0, 3, GL_INT, GL_FALSE, offsetof(VertexAttribs, vertex));
vbo_.getOfs(offsetof(VertexAttribs, vertex))); glVertexArrayAttribBinding(vertexArray_, 0, 0);
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)));
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(), sizeof(VertexAttribs)*vertexAttribs.size(),
vertexAttribs.data()); vertexAttribs.data());
@@ -526,7 +527,7 @@ namespace render {
indexOfs_ = sizeof(VertexAttribs)*vertexAttribs.size(); indexOfs_ = sizeof(VertexAttribs)*vertexAttribs.size();
numIndices_ = indices.size(); numIndices_ = indices.size();
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, vbo_.getBase()+indexOfs_, glNamedBufferSubData(vbo_.getVBOId(), vbo_.getBase()+indexOfs_,
2*numIndices_, 2*numIndices_,
indices.data()); indices.data());
@@ -560,13 +561,13 @@ namespace render {
glUniform1i(2, 0); glUniform1i(2, 0);
glUniform1i(3, 1); glUniform1i(3, 1);
glBindTexture(GL_TEXTURE_2D, tex_);
if (texAnim_) { if (texAnim_) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D_ARRAY, texAnim_);
glActiveTexture(GL_TEXTURE0);
glUniform1ui(4, animFrame_); glUniform1ui(4, animFrame_);
}
std::array<GLuint, 2> texs{tex_, texAnim_};
glBindTextures(0, 2, texs.data());
} else
glBindTextures(0, 1, &tex_.get());
glBindVertexArray(vertexArray_); glBindVertexArray(vertexArray_);

View File

@@ -21,12 +21,12 @@ namespace render {
vbo_(VBOManager::getInstance().alloc(sizeof(VertexAttribs)*6)), vbo_(VBOManager::getInstance().alloc(sizeof(VertexAttribs)*6)),
width_(width), height_(height), top_(top), left_(left), intWidth_(intWidth), intHeight_(intHeight) 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)); glTextureParameteri(texture_, GL_TEXTURE_MAG_FILTER, static_cast<int>(GL_NEAREST));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<int>(GL_CLAMP_TO_EDGE)); glTextureParameteri(texture_, 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_WRAP_T, static_cast<int>(GL_CLAMP_TO_EDGE));
program_ = ProgramProvider::getInstance().getProgram("overlay", "overlay"); 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_; short int t = top_, l = left_, b = height+top_, r = width+left_;
std::vector<VertexAttribs> vertexAttribs{ std::vector<VertexAttribs> vertexAttribs{
{{l, t}, {0, 0}}, {{l, t}, {0, 0}},
@@ -36,19 +36,17 @@ namespace render {
{{l, b}, {0, 65535u}}, {{l, b}, {0, 65535u}},
{{r, b}, {65535u, 65535u}}}; {{r, b}, {65535u, 65535u}}};
glBindBuffer(GL_ARRAY_BUFFER, vbo_.getVBOId()); glVertexArrayVertexBuffer(vertexArray_, 0, vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs));
glBindVertexArray(vertexArray_);
glEnableVertexAttribArray(0); glEnableVertexArrayAttrib(vertexArray_, 0);
glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE, sizeof(VertexAttribs), glVertexArrayAttribFormat(vertexArray_, 0, 2, GL_SHORT, GL_FALSE, offsetof(VertexAttribs, vertex));
vbo_.getOfs(offsetof(VertexAttribs, vertex))); glVertexArrayAttribBinding(vertexArray_, 0, 0);
glEnableVertexAttribArray(1); glEnableVertexArrayAttrib(vertexArray_, 1);
glVertexAttribPointer(1, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(VertexAttribs), glVertexArrayAttribFormat(vertexArray_, 1, 2, GL_UNSIGNED_SHORT, GL_TRUE, offsetof(VertexAttribs, texCoords));
vbo_.getOfs(offsetof(VertexAttribs, texCoords))); glVertexArrayAttribBinding(vertexArray_, 1, 0);
glBufferSubData(GL_ARRAY_BUFFER, vbo_.getBase(), glNamedBufferSubData(vbo_.getVBOId(), vbo_.getBase(), sizeof(VertexAttribs)*6,
sizeof(VertexAttribs)*6, vertexAttribs.data());
vertexAttribs.data());
ovlProj_ = glm::ortho(0.0f, static_cast<float>(renderer_.getWidth()), ovlProj_ = glm::ortho(0.0f, static_cast<float>(renderer_.getWidth()),
static_cast<float>(renderer_.getHeight()), 0.0f); static_cast<float>(renderer_.getHeight()), 0.0f);
@@ -84,27 +82,23 @@ namespace render {
(content->w > intWidth_)) (content->w > intWidth_))
throw Exception{"null or mismatched surface"}; throw Exception{"null or mismatched surface"};
glBindTexture(GL_TEXTURE_2D, texture_);
if (content->format->format != SDL_PIXELFORMAT_ARGB8888) { if (content->format->format != SDL_PIXELFORMAT_ARGB8888) {
printf("Warning: Format conversion in Overlay::setContent\n"); printf("Warning: Format conversion in Overlay::setContent\n");
SDLSurfaceUPtr tmpSurf(SDL_ConvertSurfaceFormat(content, SDL_PIXELFORMAT_ARGB8888, 0)); SDLSurfaceUPtr tmpSurf(SDL_ConvertSurfaceFormat(content, SDL_PIXELFORMAT_ARGB8888, 0));
if (!tmpSurf) if (!tmpSurf)
throw SDLException{}; 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 } 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) void Overlay::setContentRGB8(void *data)
{ {
glBindTexture(GL_TEXTURE_2D, texture_); glTextureSubImage2D(texture_, 0, 0, 0, intWidth_, intHeight_, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, intWidth_, intHeight_, GL_RGB, GL_UNSIGNED_BYTE, data);
} }
void Overlay::setContentBGRA8(void *data) void Overlay::setContentBGRA8(void *data)
{ {
glBindTexture(GL_TEXTURE_2D, texture_); glTextureSubImage2D(texture_, 0, 0, 0, intWidth_, intHeight_, GL_BGRA, GL_UNSIGNED_BYTE, data);
glTexSubImage2D(GL_TEXTURE_2D, 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)), ShaderResource vs(glCreateShader(GL_VERTEX_SHADER)),
fs(glCreateShader(GL_FRAGMENT_SHADER)); fs(glCreateShader(GL_FRAGMENT_SHADER));
shaderCompile_(vertexShader + ".vs", vs); shaderCompile_(vertexShader + ".vert", vs);
shaderCompile_(fragShader + ".fs", fs); shaderCompile_(fragShader + ".frag", fs);
ProgramResource prog(glCreateProgram()); ProgramResource prog(glCreateProgram());
glAttachShader(prog, vs); 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) Renderer::Renderer(bool fullscreen)
: sdlInit_(), ttfInit_(), window_(), context_() : sdlInit_(), ttfInit_(), window_(), context_()
{ {
// Initialize OpenGL
glbinding::Binding::initialize();
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
@@ -79,6 +81,9 @@ namespace render {
context_ = SDLGLContext(window_.get()); context_ = SDLGLContext(window_.get());
// Initialize OpenGL
glbinding::Binding::initialize();
SDL_GetWindowSize(window_.get(), &width_, &height_); SDL_GetWindowSize(window_.get(), &width_, &height_);
glbinding::setCallbackMask(glbinding::CallbackMask::After); glbinding::setCallbackMask(glbinding::CallbackMask::After);
@@ -95,6 +100,14 @@ namespace render {
} }
#endif #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); glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glViewport(0, 0, width_, height_); 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 { try {
return vbo.alloc(size); return vbo.alloc(size);
} catch (AllocFailed &ex) { } 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) : _bufID(0)
{ {
glGenBuffers(1, &_bufID); glCreateBuffers(1, &_bufID);
glBindBuffer(GL_ARRAY_BUFFER, _bufID); glNamedBufferStorage(_bufID, size, NULL, GL_DYNAMIC_STORAGE_BIT);
glBufferData(GL_ARRAY_BUFFER, size, NULL, type);
_allocs.emplace_back(_Entry{size, false}); _allocs.emplace_back(_Entry{size, false});
} }

View File

@@ -19,7 +19,6 @@ namespace render {
static const size_t default_size; static const size_t default_size;
static const size_t alignment = 4; static const size_t alignment = 4;
static const gl::GLenum default_type = gl::GL_STATIC_DRAW;
class AllocFailed {}; class AllocFailed {};
@@ -72,13 +71,13 @@ namespace render {
size_t _ofs, _size; size_t _ofs, _size;
}; };
VBOAlloc alloc(size_t size, gl::GLenum type = default_type); VBOAlloc alloc(size_t size);
private: private:
class VBO { class VBO {
public: public:
VBO(size_t size = default_size, gl::GLenum type = default_type); VBO(size_t size = default_size);
VBO(VBO const& copy) = delete; VBO(VBO const& copy) = delete;
VBO& operator=(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 create2DTexture(unsigned width, unsigned height, bool alpha, unsigned levels)
{ {
TextureResource tex; 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); unsigned logWidth = ilog2(width), logHeight = ilog2(height);
if (levels == 0) if (levels == 0)
levels = std::max(logWidth,logHeight)+1u; levels = std::max(logWidth,logHeight)+1u;
if(extensionSupported("GL_ARB_texture_storage")) glTextureStorage2D(tex, levels, alpha?GL_RGBA8:GL_RGB8, width, height);
glTexStorage2D(GL_TEXTURE_2D, levels, alpha?GL_RGBA8:GL_RGB8, width, height);
else { glTextureParameteri(tex, GL_TEXTURE_MAX_LEVEL, levels-1);
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);
return tex; return tex;
} }
@@ -83,27 +73,16 @@ namespace render {
bool alpha, unsigned levels) bool alpha, unsigned levels)
{ {
TextureResource tex; 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); unsigned logWidth = ilog2(width), logHeight = ilog2(height);
if (levels == 0) if (levels == 0)
levels = std::max(logWidth,logHeight)+1u; levels = std::max(logWidth,logHeight)+1u;
if(extensionSupported("GL_ARB_texture_storage")) glTextureStorage3D(tex, levels, alpha?GL_RGBA8:GL_RGB8, width, height, count);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, levels, alpha?GL_RGBA8:GL_RGB8, width, height, count);
else { glTextureParameteri(tex, GL_TEXTURE_MAX_LEVEL, levels-1);
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);
return tex; return tex;
} }