Added SDL_Texture wrapper class and some utility functions
This commit is contained in:
parent
5c430f6096
commit
56a793c086
11 changed files with 269 additions and 27 deletions
|
@ -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" />
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
sdl/exception.cpp
|
||||
sdl/rect.cpp
|
||||
sdl/surface.cpp
|
||||
sdl/texture.cpp
|
||||
sdl/utils.cpp
|
||||
sdl/window.cpp
|
||||
tracer.cpp
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -554,7 +554,7 @@ void sdl_event_handler::draw()
|
|||
}
|
||||
|
||||
// Finally, render the screen.
|
||||
video.flip();
|
||||
video.render_screen();
|
||||
}
|
||||
|
||||
void sdl_event_handler::draw_everything()
|
||||
|
|
|
@ -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
132
src/sdl/texture.cpp
Normal 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
96
src/sdl/texture.hpp
Normal 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_;
|
||||
};
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Reference in a new issue