#include "ArrayTexture.hpp"
+#include "CubeMap.hpp"
#include "Font.hpp"
#include "Format.hpp"
#include "Texture.hpp"
+#include "TextureBase.hpp"
#include "Viewport.hpp"
-#include "../app/init.hpp"
+#include "../app/error.hpp"
#include <algorithm>
#include <cstring>
+#include <iostream>
#include <memory>
#include <stdexcept>
Font::Font(const char *src, int size, long index)
: handle(TTF_OpenFontIndex(src, size, index)) {
if (!handle) {
- throw std::runtime_error(TTF_GetError());
+ throw TTFError("TTF_OpenFontIndex");
}
}
glm::ivec2 Font::TextSize(const char *text) const {
glm::ivec2 size;
if (TTF_SizeUTF8(handle, text, &size.x, &size.y) != 0) {
- throw std::runtime_error(TTF_GetError());
+ throw TTFError("TTF_SizeUTF8");
}
return size;
}
void Font::Render(const char *text, Texture &tex) const {
SDL_Surface *srf = TTF_RenderUTF8_Blended(handle, text, { 0xFF, 0xFF, 0xFF, 0xFF });
if (!srf) {
- throw std::runtime_error(TTF_GetError());
+ throw TTFError("TTF_RenderUTF8_Blended");
}
tex.Bind();
tex.Data(*srf, false);
SDL_FreeSurface(srf);
}
-Format::Format()
+Format::Format() noexcept
: format(GL_BGRA)
, type(GL_UNSIGNED_INT_8_8_8_8_REV)
, internal(GL_RGBA8) {
sdl_format.next = nullptr;
}
-Format::Format(const SDL_PixelFormat &fmt)
+Format::Format(const SDL_PixelFormat &fmt) noexcept
: sdl_format(fmt) {
if (fmt.BytesPerPixel == 4) {
if (fmt.Amask == 0xFF) {
}
+template<GLenum TARGET, GLsizei COUNT>
+TextureBase<TARGET, COUNT>::TextureBase() {
+ glGenTextures(COUNT, handle);
+}
+
+template<GLenum TARGET, GLsizei COUNT>
+TextureBase<TARGET, COUNT>::~TextureBase() {
+ glDeleteTextures(COUNT, handle);
+}
+
+template<GLenum TARGET, GLsizei COUNT>
+TextureBase<TARGET, COUNT>::TextureBase(TextureBase &&other) noexcept {
+ std::memcpy(handle, other.handle, sizeof(handle));
+ std::memset(other.handle, 0, sizeof(handle));
+}
+
+template<GLenum TARGET, GLsizei COUNT>
+TextureBase<TARGET, COUNT> &TextureBase<TARGET, COUNT>::operator =(TextureBase &&other) noexcept {
+ std::swap(handle, other.handle);
+ return *this;
+}
+
+
Texture::Texture()
-: handle(0)
+: TextureBase()
, width(0)
, height(0) {
- glGenTextures(1, &handle);
+
}
Texture::~Texture() {
- if (handle != 0) {
- glDeleteTextures(1, &handle);
- }
+
}
Texture::Texture(Texture &&other) noexcept
-: handle(other.handle) {
- other.handle = 0;
+: TextureBase(std::move(other)) {
width = other.width;
height = other.height;
}
Texture &Texture::operator =(Texture &&other) noexcept {
- std::swap(handle, other.handle);
+ TextureBase::operator =(std::move(other));
width = other.width;
height = other.height;
return *this;
}
-void Texture::Bind() noexcept {
- glBindTexture(GL_TEXTURE_2D, handle);
-}
-
namespace {
bool ispow2(unsigned int i) {
// don't care about i == 0 here
UnpackRowLength(0);
} else if (srf.w > (1 << 30) || srf.h > (1 << 30)) {
+ // That's at least one gigapixel in either or both dimensions.
+ // If this is not an error, that's an insanely large or high
+ // resolution texture.
#ifndef NDEBUG
- throw std::runtime_error("texture too large");
+ std::cerr << "texture size exceeds 2^30, aborting data import" << std::endl;
#endif
} else {
GLsizei width = 1, height = 1;
}
-void Texture::FilterNearest() noexcept {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-}
-
-void Texture::FilterLinear() noexcept {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-}
-
-void Texture::FilterTrilinear() noexcept {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glGenerateMipmap(GL_TEXTURE_2D);
-}
-
-
void Texture::UnpackAlignment(GLint i) noexcept {
glPixelStorei(GL_UNPACK_ALIGNMENT, i);
}
ArrayTexture::ArrayTexture()
-: handle(0)
+: TextureBase()
, width(0)
, height(0)
, depth(0) {
- glGenTextures(1, &handle);
+
}
ArrayTexture::~ArrayTexture() {
- if (handle != 0) {
- glDeleteTextures(1, &handle);
- }
+
}
ArrayTexture::ArrayTexture(ArrayTexture &&other) noexcept
-: handle(other.handle) {
- other.handle = 0;
+: TextureBase(std::move(other)) {
width = other.width;
height = other.height;
depth = other.depth;
}
ArrayTexture &ArrayTexture::operator =(ArrayTexture &&other) noexcept {
- std::swap(handle, other.handle);
+ TextureBase::operator =(std::move(other));
width = other.width;
height = other.height;
depth = other.depth;
}
-void ArrayTexture::Bind() noexcept {
- glBindTexture(GL_TEXTURE_2D_ARRAY, handle);
-}
-
-
void ArrayTexture::Reserve(GLsizei w, GLsizei h, GLsizei d, const Format &f) noexcept {
glTexStorage3D(
GL_TEXTURE_2D_ARRAY, // which
}
-void ArrayTexture::FilterNearest() noexcept {
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+CubeMap::CubeMap()
+: TextureBase() {
+
+}
+
+CubeMap::~CubeMap() {
+
+}
+
+CubeMap::CubeMap(CubeMap &&other) noexcept
+: TextureBase(std::move(other)) {
+
}
-void ArrayTexture::FilterLinear() noexcept {
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+CubeMap &CubeMap::operator =(CubeMap &&other) noexcept {
+ TextureBase::operator =(std::move(other));
+ return *this;
+}
+
+
+void CubeMap::Data(Face f, const SDL_Surface &srf) {
+ Format format;
+ Format fmt(*srf.format);
+ if (format.Compatible(fmt)) {
+ Data(f, srf.w, srf.h, fmt, srf.pixels);
+ } else {
+ SDL_Surface *converted = SDL_ConvertSurface(
+ const_cast<SDL_Surface *>(&srf),
+ &format.sdl_format,
+ 0
+ );
+ if (!converted) {
+ throw SDLError("SDL_ConvertSurface");
+ }
+ Format new_fmt(*converted->format);
+ if (!format.Compatible(new_fmt)) {
+ SDL_FreeSurface(converted);
+ throw std::runtime_error("unable to convert texture input");
+ }
+ Data(f, converted->w, converted->h, new_fmt, converted->pixels);
+ SDL_FreeSurface(converted);
+ }
}
-void ArrayTexture::FilterTrilinear() noexcept {
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
+void CubeMap::Data(Face face, GLsizei w, GLsizei h, const Format &f, GLvoid *data) noexcept {
+ glTexImage2D(
+ face, // which
+ 0, // mipmap level
+ f.internal, // internal format
+ w, h, // size
+ 0, // border
+ f.format, f.type, // pixel format
+ data // pixel data
+ );
}
}