mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-07 12:00:02 +00:00
Re-added SDL_Texture wrapper and render utils
These were from the last attempt at accelerated rendering. We might be getting somewhere this time...
This commit is contained in:
parent
fe69a7f501
commit
0a265d1c51
@ -1,6 +1,7 @@
|
||||
sdl/exception.cpp
|
||||
sdl/rect.cpp
|
||||
sdl/surface.cpp
|
||||
sdl/texture.cpp
|
||||
sdl/utils.cpp
|
||||
sdl/window.cpp
|
||||
tracer.cpp
|
||||
|
160
src/sdl/render_utils.hpp
Normal file
160
src/sdl/render_utils.hpp
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
Copyright (C) 2017 - 2022
|
||||
Part of the Battle for Wesnoth Project https://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/rect.hpp"
|
||||
#include "sdl/texture.hpp"
|
||||
#include "video.hpp"
|
||||
|
||||
#include <SDL2/SDL_rect.h>
|
||||
#include <SDL2/SDL_render.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
|
||||
/**
|
||||
* Sets the renderer output target to the specified texture.
|
||||
*/
|
||||
class render_target_setter
|
||||
{
|
||||
public:
|
||||
explicit render_target_setter(texture& t)
|
||||
: renderer_(CVideo::get_singleton().get_renderer())
|
||||
, last_target_(nullptr)
|
||||
{
|
||||
if(renderer_) {
|
||||
// Validate we can render to this texture.
|
||||
assert(t.get_info().access == SDL_TEXTUREACCESS_TARGET);
|
||||
|
||||
last_target_ = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, t);
|
||||
}
|
||||
}
|
||||
|
||||
~render_target_setter()
|
||||
{
|
||||
if(renderer_) {
|
||||
SDL_SetRenderTarget(renderer_, last_target_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SDL_Renderer* renderer_;
|
||||
SDL_Texture* last_target_; // TODO: use the texture wrapper?
|
||||
};
|
||||
|
||||
using sdl_rect_getter = void (*)(SDL_Renderer*, SDL_Rect*);
|
||||
using sdl_rect_setter = int (*)(SDL_Renderer*, const SDL_Rect*);
|
||||
|
||||
/**
|
||||
* Base class for renderer RAII helpers that operate on SDL_Rects.
|
||||
*
|
||||
* @tparam G Getter function. Will fetch the current applicable rect.
|
||||
* That will be restored as the applicable state once this object is destroyed.
|
||||
* @tparam S Setter function.
|
||||
*/
|
||||
template<sdl_rect_getter G, sdl_rect_setter S>
|
||||
class render_raii_rect_setter_base
|
||||
{
|
||||
public:
|
||||
explicit render_raii_rect_setter_base(SDL_Rect* rect)
|
||||
: operate_(rect != nullptr)
|
||||
, last_rect_()
|
||||
, renderer_(CVideo::get_singleton().get_renderer())
|
||||
{
|
||||
if(renderer_ && operate_) {
|
||||
std::invoke(G, renderer_, &last_rect_);
|
||||
std::invoke(S, renderer_, rect);
|
||||
}
|
||||
}
|
||||
|
||||
~render_raii_rect_setter_base()
|
||||
{
|
||||
if(renderer_ && operate_) {
|
||||
if(last_rect_ != sdl::empty_rect) {
|
||||
std::invoke(S, renderer_, &last_rect_);
|
||||
} else {
|
||||
std::invoke(S, renderer_, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const bool operate_;
|
||||
SDL_Rect last_rect_;
|
||||
SDL_Renderer* renderer_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the renderer clip rect.
|
||||
*/
|
||||
using render_clip_rect_setter = render_raii_rect_setter_base<
|
||||
&SDL_RenderGetClipRect,
|
||||
&SDL_RenderSetClipRect>;
|
||||
|
||||
/**
|
||||
* Sets the renderer viewport rect.
|
||||
*/
|
||||
using render_viewport_setter = render_raii_rect_setter_base<
|
||||
&SDL_RenderGetViewport,
|
||||
&SDL_RenderSetViewport>;
|
||||
|
||||
|
||||
/**
|
||||
* Set renderer drawing color.
|
||||
*/
|
||||
inline void set_draw_color(SDL_Renderer* renderer, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
SDL_SetRenderDrawColor(renderer, r, g, b, a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set renderer drawing color.
|
||||
*/
|
||||
inline void set_draw_color(SDL_Renderer* renderer, color_t color)
|
||||
{
|
||||
set_draw_color(renderer, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
/*
|
||||
* TEXTURE SETTERS =========================================================================
|
||||
* Need to decide if these need their own file.
|
||||
*/
|
||||
|
||||
inline void set_texture_alpha(texture& t, uint8_t amount)
|
||||
{
|
||||
SDL_SetTextureAlphaMod(t, amount);
|
||||
}
|
||||
|
||||
inline void set_texture_blend_color(texture& t, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
SDL_SetTextureColorMod(t, r, g, b);
|
||||
}
|
||||
|
||||
inline void set_texture_blend_mode(texture& t, SDL_BlendMode mode)
|
||||
{
|
||||
SDL_SetTextureBlendMode(t, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the texture scale quality. Note this should be called *before* a texture
|
||||
* is created, since the hint has no effect on existing textures or render ops.
|
||||
*
|
||||
* @param value The scaling mode. Use either 'linear' or 'nearest'.
|
||||
*/
|
||||
inline void set_texture_scale_quality(const std::string& value)
|
||||
{
|
||||
SDL_SetHintWithPriority(SDL_HINT_RENDER_SCALE_QUALITY, value.c_str(), SDL_HINT_OVERRIDE);
|
||||
}
|
119
src/sdl/texture.cpp
Normal file
119
src/sdl/texture.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright (C) 2017 - 2022
|
||||
Part of the Battle for Wesnoth Project https://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/render_utils.hpp"
|
||||
#include "sdl/surface.hpp"
|
||||
#include "video.hpp"
|
||||
|
||||
static lg::log_domain log_sdl("SDL");
|
||||
#define ERR_SDL LOG_STREAM(err, log_sdl)
|
||||
|
||||
namespace
|
||||
{
|
||||
// The default pixel format to create textures with.
|
||||
const int default_texture_format = SDL_PIXELFORMAT_ARGB8888;
|
||||
|
||||
void cleanup_texture(SDL_Texture* t)
|
||||
{
|
||||
if(t != nullptr) {
|
||||
SDL_DestroyTexture(t);
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
texture::texture()
|
||||
: texture_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
texture::texture(SDL_Texture* txt)
|
||||
: texture_(txt, &cleanup_texture)
|
||||
{
|
||||
finalize();
|
||||
}
|
||||
|
||||
texture::texture(const surface& surf)
|
||||
: texture_(nullptr)
|
||||
{
|
||||
SDL_Renderer* renderer = CVideo::get_singleton().get_renderer();
|
||||
if(!renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
texture_.reset(SDL_CreateTextureFromSurface(renderer, surf), &cleanup_texture);
|
||||
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);
|
||||
}
|
||||
|
||||
void texture::finalize()
|
||||
{
|
||||
set_texture_blend_mode(*this, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
void texture::reset()
|
||||
{
|
||||
if(texture_) {
|
||||
texture_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void texture::reset(int w, int h, SDL_TextureAccess access)
|
||||
{
|
||||
// No-op if texture is null.
|
||||
reset();
|
||||
|
||||
SDL_Renderer* renderer = CVideo::get_singleton().get_renderer();
|
||||
if(!renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
texture_.reset(SDL_CreateTexture(renderer, default_texture_format, access, w, h), &cleanup_texture);
|
||||
if(!texture_) {
|
||||
ERR_SDL << "When creating texture: " << SDL_GetError() << std::endl;
|
||||
}
|
||||
|
||||
finalize();
|
||||
}
|
||||
|
||||
void texture::assign(SDL_Texture* t)
|
||||
{
|
||||
texture_.reset(t, &cleanup_texture);
|
||||
}
|
||||
|
||||
texture& texture::operator=(texture&& t)
|
||||
{
|
||||
texture_ = std::move(t.texture_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
texture::info::info(SDL_Texture* t)
|
||||
: format(0)
|
||||
, access(0)
|
||||
, w(0)
|
||||
, h(0)
|
||||
{
|
||||
SDL_QueryTexture(t, &format, &access, &w, &h);
|
||||
}
|
89
src/sdl/texture.hpp
Normal file
89
src/sdl/texture.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright (C) 2017 - 2022
|
||||
Part of the Battle for Wesnoth Project https://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 <SDL2/SDL_render.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
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();
|
||||
|
||||
texture(const texture&) = default;
|
||||
|
||||
/** 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);
|
||||
|
||||
/** Small wrapper that queries metadata about the provided texture. */
|
||||
struct info
|
||||
{
|
||||
explicit info(SDL_Texture* t);
|
||||
|
||||
uint32_t format;
|
||||
int access;
|
||||
int w;
|
||||
int h;
|
||||
};
|
||||
|
||||
/** Queries metadata about the texture, such as its dimensions. */
|
||||
const info get_info() const
|
||||
{
|
||||
return info(*this);
|
||||
}
|
||||
|
||||
/** Releases ownership of the managed texture and resets the ptr to null. */
|
||||
void reset();
|
||||
|
||||
/** Releases ownership of the managed texture and creates a new one. */
|
||||
void reset(int w, int h, SDL_TextureAccess access);
|
||||
|
||||
/** Replaces ownership of the managed texture with the given one. */
|
||||
void assign(SDL_Texture* t);
|
||||
|
||||
texture& operator=(const texture& t) = default;
|
||||
|
||||
/** Move assignment. Releases ownership of the managed texture from the passed object. */
|
||||
texture& operator=(texture&& t);
|
||||
|
||||
operator SDL_Texture*() const
|
||||
{
|
||||
return texture_.get();
|
||||
}
|
||||
|
||||
bool null() const
|
||||
{
|
||||
return texture_ == nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void finalize();
|
||||
|
||||
std::shared_ptr<SDL_Texture> texture_;
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user