Skip to content

Commit

Permalink
Added SDL_Texture wrapper class and some utility functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Vultraz committed Jul 9, 2017
1 parent eb33c18 commit cb90c50
Show file tree
Hide file tree
Showing 11 changed files with 270 additions and 27 deletions.
2 changes: 2 additions & 0 deletions projectfiles/CodeBlocks/wesnoth.cbp
Expand Up @@ -994,6 +994,8 @@
<Unit filename="../../src/sdl/rect.cpp" />
<Unit filename="../../src/sdl/surface.cpp" />
<Unit filename="../../src/sdl/surface.hpp" />
<Unit filename="../../src/sdl/texture.cpp" />
<Unit filename="../../src/sdl/texture.hpp" />
<Unit filename="../../src/sdl/utils.cpp" />
<Unit filename="../../src/sdl/utils.hpp" />
<Unit filename="../../src/sdl/window.cpp" />
Expand Down
1 change: 1 addition & 0 deletions source_lists/libwesnoth_sdl
@@ -1,6 +1,7 @@
sdl/exception.cpp
sdl/rect.cpp
sdl/surface.cpp
sdl/texture.cpp
sdl/utils.cpp
sdl/window.cpp
tracer.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/display.cpp
Expand Up @@ -1336,7 +1336,7 @@ void display::flip()
font::draw_floating_labels(frameBuffer);
events::raise_volatile_draw_event();

video().flip();
video().render_screen();

events::raise_volatile_undraw_event();
font::undraw_floating_labels(frameBuffer);
Expand Down
27 changes: 7 additions & 20 deletions src/gui/core/canvas.cpp
Expand Up @@ -1191,15 +1191,13 @@ void image_shape::draw(
* To work around that, we create a texture from the surface and copy it to the renderer. This cleanly
* copies the surface to the canvas texture with the appropriate alpha blending.
*/
SDL_Texture* txt = SDL_CreateTextureFromSurface(renderer, surf);
texture txt(surf);

if(vertical_mirror_(local_variables)) {
SDL_RenderCopyEx(renderer, txt, nullptr, &dst_clip, 0, nullptr, SDL_FLIP_VERTICAL);
} else {
SDL_RenderCopy(renderer, txt, nullptr, &dst_clip);
}

SDL_DestroyTexture(txt);
}

image_shape::resize_mode image_shape::get_resize_mode(const std::string& resize_mode)
Expand Down Expand Up @@ -1389,10 +1387,9 @@ void text_shape::draw(
* To work around that, we create a texture from the surface and copy it to the renderer. This cleanly
* copies the surface to the canvas texture with the appropriate alpha blending.
*/
SDL_Texture* txt = SDL_CreateTextureFromSurface(renderer, surf);
SDL_RenderCopy(renderer, txt, nullptr, &dst);
texture txt(surf);

SDL_DestroyTexture(txt);
SDL_RenderCopy(renderer, txt, nullptr, &dst);
}

/***** ***** ***** ***** ***** CANVAS ***** ***** ***** ***** *****/
Expand All @@ -1403,7 +1400,7 @@ canvas::canvas()
, w_(0)
, h_(0)
, texture_(nullptr)
, renderer_(*CVideo::get_singleton().get_window())
, renderer_(CVideo::get_singleton().get_renderer())
, variables_()
, functions_()
, is_dirty_(true)
Expand All @@ -1413,7 +1410,6 @@ canvas::canvas()
canvas::~canvas()
{
SDL_SetRenderTarget(renderer_, nullptr);
SDL_DestroyTexture(texture_);
}

void canvas::draw(const bool force)
Expand All @@ -1432,20 +1428,13 @@ void canvas::draw(const bool force)

DBG_GUI_D << "Canvas: resetting canvas.\n";

// Recreate the texture.
if(texture_) {
SDL_DestroyTexture(texture_);
}

texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w_, h_);
// Recreate the texture. Will print an error if creation fails.
texture_.reset(w_, h_, SDL_TEXTUREACCESS_TARGET);
if(!texture_) {
ERR_GUI_D << "Error when creating canvas texture: " << SDL_GetError() << std::endl;
return;
}

SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);

SDL_SetRenderTarget(renderer_, texture_);
render_target_setter target_setter(texture_);

// Draw items.
for(auto& shape : shapes_) {
Expand All @@ -1454,8 +1443,6 @@ void canvas::draw(const bool force)
shape->draw(w_, h_, renderer_, variables_);
}

SDL_SetRenderTarget(renderer_, nullptr);

is_dirty_ = false;
}

Expand Down
4 changes: 2 additions & 2 deletions src/gui/core/canvas.hpp
Expand Up @@ -23,7 +23,7 @@
#include "config.hpp"
#include "formula/callable.hpp"
#include "formula/function.hpp"
#include "sdl/surface.hpp"
#include "sdl/texture.hpp"

namespace wfl { class variant; }

Expand Down Expand Up @@ -190,7 +190,7 @@ class canvas
unsigned h_;

/** The texture onto which items are drawn. */
SDL_Texture* texture_;
texture texture_;

/** A pointer to the window renderer. */
SDL_Renderer* renderer_;
Expand Down
2 changes: 1 addition & 1 deletion src/gui/core/event/handler.cpp
Expand Up @@ -550,7 +550,7 @@ void sdl_event_handler::draw(const bool /*force*/)
}

// Finally, render the screen.
video.flip();
video.render_screen();
}

void sdl_event_handler::video_resize(const point& new_size)
Expand Down
2 changes: 1 addition & 1 deletion src/help/help.cpp
Expand Up @@ -231,7 +231,7 @@ void show_help(CVideo& video, const section &toplevel_sec,
return;
}
}
video.flip();
video.render_screen();
CVideo::delay(10);
}
}
Expand Down
132 changes: 132 additions & 0 deletions src/sdl/texture.cpp
@@ -0,0 +1,132 @@
/*
Copyright (C) 2017 the Battle for Wesnoth Project http://www.wesnoth.org/
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 "sdl/texture.hpp"

#include "log.hpp"
#include "sdl/surface.hpp"
#include "video.hpp"

#include <cassert>
#include <iostream>

static lg::log_domain log_sdl("SDL");
#define ERR_SDL LOG_STREAM(err, log_sdl)

// The default pixel format to create textures with.
static int default_texture_format = SDL_PIXELFORMAT_ARGB8888;

texture::texture()
: texture_(nullptr)
{
}

texture::texture(SDL_Texture* txt)
: texture_(txt)
{
finalize();
}

texture::texture(const surface& surf)
: texture_(nullptr)
{
SDL_Renderer* renderer = CVideo::get_singleton().get_renderer();
if(!renderer) {
return;
}

texture_ = SDL_CreateTextureFromSurface(renderer, surf);
if(!texture_) {
ERR_SDL << "When creating texture from surface: " << SDL_GetError() << std::endl;
}
}

texture::texture(int w, int h, SDL_TextureAccess access)
: texture_(nullptr)
{
reset(w, h, access);
}

texture::~texture()
{
destroy_texture();
}

void texture::finalize()
{
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
}

void texture::reset(int w, int h, SDL_TextureAccess access)
{
// No-op if texture is null.
destroy_texture();

SDL_Renderer* renderer = CVideo::get_singleton().get_renderer();
if(!renderer) {
return;
}

texture_ = SDL_CreateTexture(renderer, default_texture_format, access, w, h);
if(!texture_) {
ERR_SDL << "When creating texture: " << SDL_GetError() << std::endl;
}

finalize();
}

void texture::destroy_texture()
{
if(texture_) {
SDL_DestroyTexture(texture_);
}
}

#if 0
texture& texture::operator=(texture&& t)
{
destroy_texture();

texture_ = t.texture_;
t.texture_ = nullptr;

return *this;
}
#endif

texture::info::info(const texture& t)
: format(0)
, access(0)
, w(0)
, h(0)
{
SDL_QueryTexture(t, &format, &access, &w, &h);
}

render_target_setter::render_target_setter(texture& t)
: renderer_(CVideo::get_singleton().get_renderer())
{
if(renderer_) {
// Validate we can render to this texture.
assert(t.get_info().access == SDL_TEXTUREACCESS_TARGET);

SDL_SetRenderTarget(renderer_, t);
}
}

render_target_setter::~render_target_setter()
{
if(renderer_) {
SDL_SetRenderTarget(renderer_, nullptr);
}
}
96 changes: 96 additions & 0 deletions src/sdl/texture.hpp
@@ -0,0 +1,96 @@
/*
Copyright (C) 2017 the Battle for Wesnoth Project http://www.wesnoth.org/
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_render.h>

class surface;

/**
* Wrapper class to encapsulate creation and management of an SDL_Texture.
* Supports free creation and creation from a surface.
*/
class texture
{
public:
/** Default ctor. Texture will be a nullptr. */
texture();

/** Assigns the given texture to this one. */
explicit texture(SDL_Texture* txt);

/** Construct a texture from a surface. */
explicit texture(const surface& surf);

/** Construct a texture of the specified size and access type. */
texture(int w, int h, SDL_TextureAccess access);

~texture();

/** Small wrapper that queries metadata about the provided texture. */
struct info
{
explicit info(const texture& t);

Uint32 format;
int access;
int w;
int h;
};

/** Queries metadata about the texture, such as its dimensions. */
const info get_info() const
{
return info(*this);
}

/** Destroys the managed texture and creates a new one. */
void reset(int w, int h, SDL_TextureAccess access);

#if 0
/** Move assignment. Frees the managed texture from the passed object. */
texture& operator=(texture&& t);
#endif

operator SDL_Texture*() const
{
return texture_;
}

bool null() const
{
return texture_ == nullptr;
}

private:
void finalize();

void destroy_texture();

SDL_Texture* texture_;
};

/**
* Small RAII helper class to temporarily set the renderer target to a texture.
*/
class render_target_setter
{
public:
explicit render_target_setter(texture& t);

~render_target_setter();

private:
SDL_Renderer* renderer_;
};

0 comments on commit cb90c50

Please sign in to comment.