Added SDL_Texture wrapper class and some utility functions

This commit is contained in:
Charles Dang 2017-06-05 19:23:46 +11:00
parent 5c430f6096
commit 56a793c086
11 changed files with 269 additions and 27 deletions

View file

@ -1011,6 +1011,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" />

View file

@ -1,6 +1,7 @@
sdl/exception.cpp
sdl/rect.cpp
sdl/surface.cpp
sdl/texture.cpp
sdl/utils.cpp
sdl/window.cpp
tracer.cpp

View file

@ -1332,7 +1332,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);

View file

@ -1171,15 +1171,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)
@ -1369,10 +1367,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 ***** ***** ***** ***** *****/
@ -1384,7 +1381,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)
@ -1397,7 +1394,7 @@ canvas::canvas(canvas&& c)
, blur_depth_(c.blur_depth_)
, w_(c.w_)
, h_(c.h_)
, canvas_(std::move(c.canvas_))
, texture_(std::move(c.texture_))
, renderer_(c.renderer_)
, variables_(c.variables_)
, functions_(c.functions_)
@ -1410,7 +1407,6 @@ canvas::canvas(canvas&& c)
canvas::~canvas()
{
SDL_SetRenderTarget(renderer_, nullptr);
SDL_DestroyTexture(texture_);
}
void canvas::draw(const bool force)
@ -1439,20 +1435,13 @@ void canvas::draw(const bool force)
}
#endif
// 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_) {
@ -1461,7 +1450,6 @@ void canvas::draw(const bool force)
shape->draw(w_, h_, renderer_, variables_);
}
SDL_SetRenderTarget(renderer_, nullptr);
// TODO: re-enable
#if 0
// The shapes have been drawn and the draw result has been cached. Clear the list.

View file

@ -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; }
@ -198,7 +198,7 @@ private:
unsigned h_;
/** The texture onto which items are drawn. */
SDL_Texture* texture_;
texture texture_;
/** A pointer to the window renderer. */
SDL_Renderer* renderer_;

View file

@ -554,7 +554,7 @@ void sdl_event_handler::draw()
}
// Finally, render the screen.
video.flip();
video.render_screen();
}
void sdl_event_handler::draw_everything()

View file

@ -230,7 +230,7 @@ void show_help(const section &toplevel_sec,
return;
}
}
video.flip();
video.render_screen();
CVideo::delay(10);
}
}

132
src/sdl/texture.cpp Normal file
View file

@ -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
src/sdl/texture.hpp Normal file
View file

@ -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_;
};

View file

@ -21,6 +21,7 @@
#include "log.hpp"
#include "preferences/general.hpp"
#include "sdl/point.hpp"
#include "sdl/texture.hpp"
#include "sdl/userevent.hpp"
#include "sdl/utils.hpp"
#include "sdl/window.hpp"
@ -331,7 +332,7 @@ void CVideo::delay(unsigned int milliseconds)
}
}
void CVideo::flip()
void CVideo::render_screen()
{
if(fake_screen_ || flip_locked_ > 0) {
return;
@ -342,6 +343,13 @@ void CVideo::flip()
}
}
void CVideo::copy_to_screen(texture& txt, SDL_Rect* src_rect, SDL_Rect* dst_rect)
{
if(window) {
SDL_RenderCopy(*window, txt, src_rect, dst_rect);;
}
}
void CVideo::lock_updates(bool value)
{
if(value == true) {
@ -382,6 +390,15 @@ sdl::window* CVideo::get_window()
return window.get();
}
SDL_Renderer* CVideo::get_renderer()
{
if(!window) {
return nullptr;
}
return *window;
}
bool CVideo::window_has_flags(uint32_t flags) const
{
if(!window) {

View file

@ -21,6 +21,7 @@
#include <memory>
class surface;
class texture;
struct point;
namespace sdl
@ -72,6 +73,9 @@ public:
/** Returns a pointer to the underlying SDL window. */
sdl::window* get_window();
/** Returns a pointer to the underlying window's renderer. */
SDL_Renderer* get_renderer();
private:
enum MODE_EVENT { TO_RES, TO_FULLSCREEN, TO_WINDOWED, TO_MAXIMIZED_WINDOW };
@ -165,7 +169,9 @@ public:
void blit_surface(int x, int y, surface surf, SDL_Rect* srcrect = nullptr, SDL_Rect* clip_rect = nullptr);
/** Renders the screen. Should normally not be called directly! */
void flip();
void render_screen();
void copy_to_screen(texture& txt, SDL_Rect* src_rect = nullptr, SDL_Rect* dst_rect = nullptr);
/**
* Updates and ensures the framebuffer surface is valid.