X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fgraphics%2Frender.cpp;h=470cb191f4185ca893bdd683158b84e4042fbb15;hb=a32b120a2c06d3c7ad6a217bc46bba9e76d75d93;hp=3d0bbd47c6cf2e00feb6efb10798c22469a694a8;hpb=282d731ea8f10342efa82012028de7043b3dd639;p=blank.git diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 3d0bbd4..470cb19 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -1,6 +1,10 @@ +#include "ArrayTexture.hpp" #include "Font.hpp" #include "Format.hpp" #include "Texture.hpp" +#include "Viewport.hpp" + +#include "../app/init.hpp" #include #include @@ -34,6 +38,31 @@ Font &Font::operator =(Font &&other) noexcept { } +int Font::Style() const noexcept { + return TTF_GetFontStyle(handle); +} + +void Font::Style(int s) const noexcept { + TTF_SetFontStyle(handle, s); +} + +int Font::Outline() const noexcept { + return TTF_GetFontOutline(handle); +} + +void Font::Outline(int px) noexcept { + TTF_SetFontOutline(handle, px); +} + + +int Font::Hinting() const noexcept { + return TTF_GetFontHinting(handle); +} + +void Font::Hinting(int h) const noexcept { + TTF_SetFontHinting(handle, h); +} + bool Font::Kerning() const noexcept { return TTF_GetFontKerning(handle); } @@ -60,34 +89,71 @@ int Font::LineSkip() const noexcept { } +const char *Font::FamilyName() const noexcept { + return TTF_FontFaceFamilyName(handle); +} + +const char *Font::StyleName() const noexcept { + return TTF_FontFaceStyleName(handle); +} + + bool Font::HasGlyph(Uint16 c) const noexcept { return TTF_GlyphIsProvided(handle, c); } -glm::tvec2 Font::TextSize(const char *text) const { - glm::tvec2 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()); } return size; } -Texture Font::Render(const char *text, SDL_Color color) const { - SDL_Surface *srf = TTF_RenderUTF8_Blended(handle, text, color); +Texture Font::Render(const char *text) const { + Texture tex; + Render(text, tex); + return tex; +} + +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()); } - Texture tex; tex.Bind(); tex.Data(*srf, false); tex.FilterLinear(); SDL_FreeSurface(srf); - return tex; } +Format::Format() +: 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; +} -void Format::ReadPixelFormat(const SDL_PixelFormat &fmt) { +Format::Format(const SDL_PixelFormat &fmt) +: sdl_format(fmt) { if (fmt.BytesPerPixel == 4) { if (fmt.Amask == 0xFF) { if (fmt.Rmask == 0xFF00) { @@ -116,6 +182,10 @@ void Format::ReadPixelFormat(const SDL_PixelFormat &fmt) { } } +bool Format::Compatible(const Format &other) const noexcept { + return format == other.format && type == other.type && internal == other.internal; +} + Texture::Texture() : handle(0) @@ -157,8 +227,7 @@ namespace { } 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); @@ -256,4 +325,110 @@ void Texture::UnpackRowLength(GLint i) noexcept { glPixelStorei(GL_UNPACK_ROW_LENGTH, i); } + +ArrayTexture::ArrayTexture() +: handle(0) +, 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; + width = other.width; + height = other.height; + depth = other.depth; +} + +ArrayTexture &ArrayTexture::operator =(ArrayTexture &&other) noexcept { + std::swap(handle, other.handle); + width = other.width; + height = other.height; + depth = other.depth; + return *this; +} + + +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 + 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(&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 + ); +} + + +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); +} + +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); +} + +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); +} + }