-#include "BlendedSprite.hpp"
+#include "ArrayTexture.hpp"
+#include "CubeMap.hpp"
#include "Font.hpp"
#include "Format.hpp"
-#include "Text.hpp"
#include "Texture.hpp"
+#include "TextureBase.hpp"
#include "Viewport.hpp"
+#include "../app/init.hpp"
+
#include <algorithm>
#include <cstring>
#include <memory>
}
-glm::tvec2<int> Font::TextSize(const char *text) const {
- glm::tvec2<int> size;
+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());
}
SDL_FreeSurface(srf);
}
-
-void Format::ReadPixelFormat(const SDL_PixelFormat &fmt) {
+Format::Format() noexcept
+: format(GL_BGRA)
+, type(GL_UNSIGNED_INT_8_8_8_8_REV)
+, internal(GL_RGBA8) {
+ sdl_format.format = SDL_PIXELFORMAT_ARGB8888;
+ sdl_format.palette = nullptr;
+ sdl_format.BitsPerPixel = 32;
+ sdl_format.BytesPerPixel = 4;
+ sdl_format.Rmask = 0x00FF0000;
+ sdl_format.Gmask = 0x0000FF00;
+ sdl_format.Bmask = 0x000000FF;
+ sdl_format.Amask = 0xFF000000;
+ sdl_format.Rloss = 0;
+ sdl_format.Gloss = 0;
+ sdl_format.Bloss = 0;
+ sdl_format.Aloss = 0;
+ sdl_format.Rshift = 16;
+ sdl_format.Gshift = 8;
+ sdl_format.Bshift = 0;
+ sdl_format.Ashift = 24;
+ sdl_format.refcount = 1;
+ sdl_format.next = nullptr;
+}
+
+Format::Format(const SDL_PixelFormat &fmt) noexcept
+: sdl_format(fmt) {
if (fmt.BytesPerPixel == 4) {
if (fmt.Amask == 0xFF) {
if (fmt.Rmask == 0xFF00) {
}
}
+bool Format::Compatible(const Format &other) const noexcept {
+ return format == other.format && type == other.type && internal == other.internal;
+}
-Text::Text() noexcept
-: tex()
-, sprite()
-, bg(1.0f, 1.0f, 1.0f, 0.0f)
-, fg(1.0f, 1.0f, 1.0f, 1.0f)
-, size(0.0f)
-, pos(0.0f)
-, grav(Gravity::NORTH_WEST)
-, pivot(Gravity::NORTH_WEST)
-, dirty(false)
-, visible(false) {
+template<GLenum TARGET, GLsizei COUNT>
+TextureBase<TARGET, COUNT>::TextureBase() {
+ glGenTextures(COUNT, handle);
}
-void Text::Set(const Font &font, const char *text) {
- font.Render(text, tex);
- size = font.TextSize(text);
- dirty = true;
+template<GLenum TARGET, GLsizei COUNT>
+TextureBase<TARGET, COUNT>::~TextureBase() {
+ glDeleteTextures(COUNT, handle);
}
-void Text::Update() {
- sprite.LoadRect(size.x, size.y, align(pivot, size));
- dirty = false;
+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));
}
-void Text::Render(Viewport &viewport) noexcept {
- if (dirty) {
- Update();
- }
- BlendedSprite &prog = viewport.SpriteProgram();
- viewport.SetCursor(pos, grav);
- prog.SetM(viewport.Cursor());
- prog.SetTexture(tex);
- prog.SetBG(bg);
- prog.SetFG(fg);
- sprite.Draw();
+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
}
void Texture::Data(const SDL_Surface &srf, bool pad2) noexcept {
- Format format;
- format.ReadPixelFormat(*srf.format);
+ Format format(*srf.format);
if (!pad2 || (ispow2(srf.w) && ispow2(srf.h))) {
int align = UnpackAlignmentFromPitch(srf.pitch);
}
-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);
}
glPixelStorei(GL_UNPACK_ROW_LENGTH, i);
}
+
+ArrayTexture::ArrayTexture()
+: TextureBase()
+, width(0)
+, height(0)
+, depth(0) {
+
+}
+
+ArrayTexture::~ArrayTexture() {
+
+}
+
+ArrayTexture::ArrayTexture(ArrayTexture &&other) noexcept
+: TextureBase(std::move(other)) {
+ width = other.width;
+ height = other.height;
+ depth = other.depth;
+}
+
+ArrayTexture &ArrayTexture::operator =(ArrayTexture &&other) noexcept {
+ TextureBase::operator =(std::move(other));
+ width = other.width;
+ height = other.height;
+ depth = other.depth;
+ return *this;
+}
+
+
+void ArrayTexture::Reserve(GLsizei w, GLsizei h, GLsizei d, const Format &f) noexcept {
+ glTexStorage3D(
+ GL_TEXTURE_2D_ARRAY, // which
+ 1, // mipmap count
+ f.internal, // format
+ w, h, // dimensions
+ d // layer count
+ );
+ width = w;
+ height = h;
+ depth = d;
+ format = f;
+}
+
+void ArrayTexture::Data(GLsizei l, const SDL_Surface &srf) {
+ Format fmt(*srf.format);
+ if (format.Compatible(fmt)) {
+ Data(l, 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(l, new_fmt, converted->pixels);
+ SDL_FreeSurface(converted);
+ }
+}
+
+void ArrayTexture::Data(GLsizei l, const Format &f, GLvoid *data) noexcept {
+ glTexSubImage3D(
+ GL_TEXTURE_2D_ARRAY, // which
+ 0, // mipmap lavel
+ 0, 0, // dest X and Y offset
+ l, // layer offset
+ width, height,
+ 1, // layer count
+ f.format, f.type,
+ data
+ );
+}
+
+
+CubeMap::CubeMap()
+: TextureBase() {
+
+}
+
+CubeMap::~CubeMap() {
+
+}
+
+CubeMap::CubeMap(CubeMap &&other) noexcept
+: TextureBase(std::move(other)) {
+
+}
+
+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 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
+ );
+}
+
}