diff --git a/projectfiles/VC14/wesnoth.vcxproj b/projectfiles/VC14/wesnoth.vcxproj index 1369694fa29e..eda2a94f55aa 100644 --- a/projectfiles/VC14/wesnoth.vcxproj +++ b/projectfiles/VC14/wesnoth.vcxproj @@ -2530,6 +2530,13 @@ $(IntDir)OGL\ $(IntDir)OGL\ + + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ + $(IntDir)OGL\ $(IntDir)OGL\ @@ -3878,6 +3885,7 @@ + diff --git a/projectfiles/VC14/wesnoth.vcxproj.filters b/projectfiles/VC14/wesnoth.vcxproj.filters index 160ebdd0b430..bd8d7aa9a830 100644 --- a/projectfiles/VC14/wesnoth.vcxproj.filters +++ b/projectfiles/VC14/wesnoth.vcxproj.filters @@ -1546,6 +1546,9 @@ Gui\Dialogs + + OGL + @@ -3005,6 +3008,9 @@ Gui\Dialogs + + OGL + diff --git a/source_lists/libwesnoth_sdl b/source_lists/libwesnoth_sdl index 09d83e42a4a4..2e2cba63e84d 100644 --- a/source_lists/libwesnoth_sdl +++ b/source_lists/libwesnoth_sdl @@ -1,4 +1,5 @@ ogl/context.cpp +ogl/texture.cpp ogl/utils.cpp sdl/exception.cpp sdl/rect.cpp diff --git a/src/ogl/context.cpp b/src/ogl/context.cpp index 327d18f0420d..068768cb7055 100644 --- a/src/ogl/context.cpp +++ b/src/ogl/context.cpp @@ -14,6 +14,7 @@ #include "ogl/context.hpp" #include "log.hpp" +#include "ogl/texture.hpp" #include #include @@ -54,6 +55,13 @@ void context::init(sdl::window* window) throw std::runtime_error("error initializing GLEW"); } + int maxTextureSize; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); + if(maxTextureSize < texture::MAX_DIMENSION) { + ERR_GL << "Too low texture size limit\n"; + throw std::runtime_error("too low texture size limit"); + } + // Print some information. GLint profile; glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile); diff --git a/src/ogl/texture.cpp b/src/ogl/texture.cpp new file mode 100644 index 000000000000..233fe86f9535 --- /dev/null +++ b/src/ogl/texture.cpp @@ -0,0 +1,62 @@ +/* + Copyright (C) 2018 by Jyrki Vesterinen + + 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 2 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. + + See the COPYING file for more details. +*/ + +#include "ogl/texture.hpp" + +#include + +#include +#include + +namespace gl +{ + +std::pair texture::get_size() const +{ + std::pair size; + glBindTexture(GL_TEXTURE_2D, name_); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &size.first); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &size.second); + glBindTexture(GL_TEXTURE_2D, 0u); + return size; +} + +void texture::set_size(const std::pair& size) +{ + if(size.first > MAX_DIMENSION || size.second > MAX_DIMENSION) { + throw std::invalid_argument("Too large texture size"); + } + + glBindTexture(GL_TEXTURE_2D, name_); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size.first, size.second, 0, + GL_BGRA, GL_UNSIGNED_BYTE, nullptr); + glBindTexture(GL_TEXTURE_2D, 0u); +} + +void texture::set_pixels(surface pixels) +{ + assert(check_format(*pixels->format)); + surface_locker lock(pixels); + + glBindTexture(GL_TEXTURE_2D, name_); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pixels->w, pixels->h, + GL_BGRA, GL_UNSIGNED_BYTE, lock.pixels()); + glBindTexture(GL_TEXTURE_2D, 0u); +} + +bool texture::check_format(const SDL_PixelFormat& format) +{ + return format.format == SDL_PIXELFORMAT_ARGB8888; +} + +} \ No newline at end of file diff --git a/src/ogl/texture.hpp b/src/ogl/texture.hpp new file mode 100644 index 000000000000..33be60fda380 --- /dev/null +++ b/src/ogl/texture.hpp @@ -0,0 +1,80 @@ +/* + Copyright (C) 2018 by Jyrki Vesterinen + + 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 2 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. + + See the COPYING file for more details. +*/ + +#pragma once + +#include "sdl/surface.hpp" + +#include + +#include + +namespace gl +{ +/// Thin wrapper for textures. +/// All textures are two-dimensional and in the RGBA8 format. +class texture +{ +public: + static const int MAX_DIMENSION = 8192; + + /** Constructor. + Initial texture size is 0x0. Use set_size() to actually allocate memory for + the texture. */ + texture() + { + glGenTextures(1, &name_); + // Bind the texture as 2D to make it two-dimensional. + glBindTexture(GL_TEXTURE_2D, name_); + // Unbind the 2D texture target. + glBindTexture(GL_TEXTURE_2D, 0u); + } + + /// Destructor. + ~texture() + { + glDeleteTextures(1, &name_); + } + + /** @return the OpenGL texture name. + It can be passed directly to the OpenGL API. + The name of a texture does not change and can be safely cached. + */ + GLuint get_name() const + { + return name_; + } + + /// @return the size of the texture. + std::pair get_size() const; + + /** Resizes the texture. + @param size Desired texture size. + Invalidates existing content of the texture, if any. + @note Maximum texture size is 8192x8192. It's enforced both ways: Wesnoth refuses + to launch if the hardware doesn't support 8192x8192 textures, but it doesn't allow + larger textures even if the hardware supports them. */ + void set_size(const std::pair& size); + + /** Uploads the provided texture data. + @param pixels Texture data. */ + void set_pixels(surface pixels); + +private: + /// OpenGL texture name. + GLuint name_; + + /// Checks that the SDL surface format matches the format we expect. + static bool check_format(const SDL_PixelFormat& format); +}; +}