unique_ptr based management for SDL_Surfaces

This commit is contained in:
2015-03-08 13:59:08 +01:00
parent 31e3a307b5
commit ffbc59140a
6 changed files with 80 additions and 50 deletions

View File

@@ -2,7 +2,7 @@ CXX=g++
CXXOPTS=-O2 -ggdb -Wall -Wextra -pedantic -Wno-unused-function -Wno-unused-parameter -Wno-sign-compare -std=c++14 -flto CXXOPTS=-O2 -ggdb -Wall -Wextra -pedantic -Wno-unused-function -Wno-unused-parameter -Wno-sign-compare -std=c++14 -flto
LDOPTS= LDOPTS=
LIBS=-lglbinding -lSDL2 -lSDL2_image -lobj -lSDL2_ttf -lprotobuf LIBS=-lglbinding -lSDL2 -lSDL2_image -lobj -lSDL2_ttf -lprotobuf
CXXSRCS=main.cc objectParser.cc shaders.cc Object.cc VBOManager.cc texture.cc font.cc Overlay.cc CXXSRCS=main.cc objectParser.cc shaders.cc Object.cc VBOManager.cc texture.cc font.cc Overlay.cc TextWidget.cc
BINIFY_SRCS=binifyObj.cc objectParser.cc object.pb.cc BINIFY_SRCS=binifyObj.cc objectParser.cc object.pb.cc
OBJS=$(addprefix objs/,$(CXXSRCS:.cc=.o)) OBJS=$(addprefix objs/,$(CXXSRCS:.cc=.o))
BINIFY_OBJS=$(addprefix objs/,$(BINIFY_SRCS:.cc=.o)) BINIFY_OBJS=$(addprefix objs/,$(BINIFY_SRCS:.cc=.o))

View File

@@ -5,6 +5,7 @@
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
#include <cerrno> #include <cerrno>
#include <memory>
#include <glbinding/gl/gl.h> #include <glbinding/gl/gl.h>
@@ -136,4 +137,13 @@ enum class VAFormats {
VertexNormalTexcoord VertexNormalTexcoord
}; };
struct SDLSurfaceDeleter {
void operator()(SDL_Surface* ptr) const
{
SDL_FreeSurface(ptr);
}
};
using SDLSurfaceUPtr = std::unique_ptr<SDL_Surface, SDLSurfaceDeleter>;
#endif #endif

47
font.cc
View File

@@ -10,32 +10,49 @@ Font::Font(std::string const& filename, unsigned ptsize)
{ {
assert(TTF_WasInit()); assert(TTF_WasInit());
font_ = TTF_OpenFont(filename.c_str(), ptsize); font_ = TTF_OpenFont(filename.c_str(), ptsize);
if(!font_) if (!font_)
throw TTFException{}; throw TTFException{};
} }
Font::Font(Font&& move)
: font_(move.font_)
{
move.font_ = nullptr;
}
Font& Font::operator=(Font&& move)
{
if (font_)
TTF_CloseFont(font_);
font_ = move.font_;
move.font_ = nullptr;
return *this;
}
Font::~Font() Font::~Font()
{ {
if(font_) if (font_)
TTF_CloseFont(font_); TTF_CloseFont(font_);
} }
Texture2D Font::render(std::string const& text, bool fast) const { Texture2D Font::render(std::string const& text, bool fast) const
SDL_Surface *surf; {
if(fast) SDLSurfaceUPtr surf;
surf = TTF_RenderUTF8_Solid(font_, text.c_str(), SDL_Color{255, 255, 255, 255}); if (fast)
surf.reset(TTF_RenderUTF8_Solid(font_, text.c_str(), SDL_Color{255, 255, 255, 255}));
else else
surf = TTF_RenderUTF8_Blended(font_, text.c_str(), SDL_Color{255, 255, 255, 255}); surf.reset(TTF_RenderUTF8_Blended(font_, text.c_str(), SDL_Color{255, 255, 255, 255}));
if(!surf) if (!surf)
throw TTFException{}; throw TTFException{};
try { Texture2D ret{surf.get()};
Texture2D ret{surf};
SDL_FreeSurface(surf);
return ret; return ret;
} catch(...) { }
SDL_FreeSurface(surf);
throw; TTF_Font* Font::getFont() const
} {
return font_;
} }

View File

@@ -10,14 +10,17 @@ class Texture2D;
class Font { class Font {
public: public:
Font(std::string const& filename, unsigned ptsize); Font(std::string const& filename, unsigned ptsize);
Font(Font&& move);
Font(Font const& copy) = delete; Font(Font const& copy) = delete;
Font& operator=(Font&& move);
Font& operator=(Font const& copy) = delete; Font& operator=(Font const& copy) = delete;
~Font(); ~Font();
Texture2D render(std::string const& text, bool fast = false) const; Texture2D render(std::string const& text, bool fast = false) const;
TTF_Font* getFont() const;
private: private:
TTF_Font* font_; TTF_Font* font_;
}; };

View File

@@ -101,6 +101,10 @@ void TextureCubeMap::bind() const
glBindTexture(GL_TEXTURE_CUBE_MAP, _texID); glBindTexture(GL_TEXTURE_CUBE_MAP, _texID);
} }
Texture2D::Texture2D()
: texID_(0), width_(0), height_(0), alpha_(false)
{
}
Texture2D::Texture2D(unsigned width, unsigned height, bool alpha) Texture2D::Texture2D(unsigned width, unsigned height, bool alpha)
: texID_(0), width_(width), height_(height), alpha_(alpha) : texID_(0), width_(width), height_(height), alpha_(alpha)
@@ -111,7 +115,8 @@ Texture2D::Texture2D(unsigned width, unsigned height, bool alpha)
Texture2D::Texture2D(std::string const& file) Texture2D::Texture2D(std::string const& file)
: texID_(0), width_(0), height_(0), alpha_(false) : texID_(0), width_(0), height_(0), alpha_(false)
{ {
SDL_Surface *surf = IMG_Load(file.c_str()); SDLSurfaceUPtr surf(IMG_Load(file.c_str()));
if (!surf) if (!surf)
throw SDLException(); throw SDLException();
@@ -122,14 +127,11 @@ Texture2D::Texture2D(std::string const& file)
} }
try { try {
copyFromSurface(surf); copyFromSurface(surf.get());
} catch (...) { } catch (...) {
glDeleteTextures(1, &texID_); glDeleteTextures(1, &texID_);
SDL_FreeSurface(surf);
throw; throw;
} }
SDL_FreeSurface(surf);
} }
Texture2D::Texture2D(SDL_Surface *surface) Texture2D::Texture2D(SDL_Surface *surface)
@@ -174,11 +176,13 @@ Texture2D::~Texture2D()
void Texture2D::bind() const void Texture2D::bind() const
{ {
assert(texID_ != 0);
glBindTexture(GL_TEXTURE_2D, texID_); glBindTexture(GL_TEXTURE_2D, texID_);
} }
void Texture2D::copyFromSurface(SDL_Surface *src) void Texture2D::copyFromSurface(SDL_Surface *src)
{ {
SDLSurfaceUPtr tmpSurf;
SDL_Surface *surf; SDL_Surface *surf;
if ((src->w > width_) || src->h > height_) if ((src->w > width_) || src->h > height_)
throw Exception("Cannot replace texture image with larger image"); throw Exception("Cannot replace texture image with larger image");
@@ -187,35 +191,29 @@ void Texture2D::copyFromSurface(SDL_Surface *src)
if ((src->format->Amask != 0) != alpha_) if ((src->format->Amask != 0) != alpha_)
throw Exception("Cannot replace texture image with mismatched alpha"); throw Exception("Cannot replace texture image with mismatched alpha");
if (src->format->Amask == 0) { if (src->format->Amask == 0) {
surf = SDL_ConvertSurfaceFormat(src, SDL_PIXELFORMAT_RGB24, 0); tmpSurf.reset(SDL_ConvertSurfaceFormat(src, SDL_PIXELFORMAT_RGB24, 0));
} else { } else {
surf = SDL_ConvertSurfaceFormat(src, SDL_PIXELFORMAT_ABGR8888, 0); tmpSurf.reset(SDL_ConvertSurfaceFormat(src, SDL_PIXELFORMAT_ABGR8888, 0));
} }
if (!surf) if (!tmpSurf)
throw SDLException{}; throw SDLException{};
surf = tmpSurf.get();
} else { } else {
surf = src; surf = src;
} }
if (SDL_MUSTLOCK(surf)) if (SDL_MUSTLOCK(surf))
SDL_LockSurface(surf); SDL_LockSurface(surf);
try {
bind(); bind();
if(surf->format->Amask == 0) if(surf->format->Amask == 0)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGB, GL_UNSIGNED_BYTE, surf->pixels); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGB, GL_UNSIGNED_BYTE, surf->pixels);
else else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
} catch(...) {
if (surf != src)
SDL_FreeSurface(surf);
throw;
}
if(surf != src)
SDL_FreeSurface(surf);
} }
SDL_Surface* Texture2D::copyToSurface() SDLSurfaceUPtr Texture2D::copyToSurface()
{ {
bind(); bind();
uint32_t rmask, gmask, bmask, amask; uint32_t rmask, gmask, bmask, amask;
@@ -223,16 +221,13 @@ SDL_Surface* Texture2D::copyToSurface()
if (!SDL_PixelFormatEnumToMasks(alpha_?SDL_PIXELFORMAT_ABGR8888:SDL_PIXELFORMAT_RGB24, if (!SDL_PixelFormatEnumToMasks(alpha_?SDL_PIXELFORMAT_ABGR8888:SDL_PIXELFORMAT_RGB24,
&bpp, &rmask, &gmask, &bmask, &amask)) &bpp, &rmask, &gmask, &bmask, &amask))
throw SDLException{}; throw SDLException{};
SDL_Surface *dst = SDL_CreateRGBSurface(0, width_, height_, bpp,
rmask, gmask, bmask, amask); SDLSurfaceUPtr dst(SDL_CreateRGBSurface(0, width_, height_, bpp,
rmask, gmask, bmask, amask));
if(!dst) if(!dst)
throw SDLException{}; throw SDLException{};
try {
glGetTexImage(GL_TEXTURE_2D, 0, alpha_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, dst->pixels); glGetTexImage(GL_TEXTURE_2D, 0, alpha_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, dst->pixels);
} catch(...) {
SDL_FreeSurface(dst);
throw;
}
return dst; return dst;
} }

View File

@@ -61,6 +61,7 @@ private:
class Texture2D { class Texture2D {
public: public:
Texture2D();
Texture2D(unsigned width, unsigned height, bool alpha = false); Texture2D(unsigned width, unsigned height, bool alpha = false);
Texture2D(std::string const& file); Texture2D(std::string const& file);
Texture2D(SDL_Surface *surface); Texture2D(SDL_Surface *surface);
@@ -76,7 +77,11 @@ public:
void bind() const; void bind() const;
void copyFromSurface(SDL_Surface *src); void copyFromSurface(SDL_Surface *src);
SDL_Surface* copyToSurface(); SDLSurfaceUPtr copyToSurface();
unsigned getWidth() const { return width_; }
unsigned getHeight() const { return height_; }
bool getAlpha() const { return alpha_; }
private: private: