The Battle for Wesnoth  1.19.24+dev
texture.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2017 - 2025
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "sdl/texture.hpp"
16 
17 #include "color.hpp"
18 #include "log.hpp"
19 #include "sdl/point.hpp"
20 #include "sdl/surface.hpp"
21 #include "video.hpp"
22 
23 static lg::log_domain log_sdl("SDL");
24 #define ERR_SDL LOG_STREAM(err, log_sdl)
25 
26 namespace
27 {
28 // The default pixel format to create textures with.
29 const SDL_PixelFormat default_texture_format = SDL_PIXELFORMAT_ARGB8888;
30 
31 void cleanup_texture(SDL_Texture* t)
32 {
33  if(t != nullptr) {
34  SDL_DestroyTexture(t);
35  }
36 }
37 
38 } // namespace
39 
40 texture::texture(SDL_Texture* txt)
41  : texture_(txt, &cleanup_texture)
42 {
43  if (txt) {
44  SDL_PropertiesID props = SDL_GetTextureProperties(txt);
45  size_.x = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_WIDTH_NUMBER, 0);
46  size_.y = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_HEIGHT_NUMBER, 0);
47  finalize();
48  }
49 }
50 
51 texture::texture(const surface& surf, bool linear_interpolation)
52  : texture()
53 {
54  if (!surf) {
55  return;
56  }
57 
58  if (surf->w == 0 && surf->h == 0) {
59  return;
60  }
61 
62  SDL_Renderer* renderer = video::get_renderer();
63  if(!renderer) {
64  return;
65  }
66 
67  texture_.reset(SDL_CreateTextureFromSurface(renderer, surf), &cleanup_texture);
68  if(!texture_) {
69  ERR_SDL << "When creating texture from surface: " << SDL_GetError();
70  }
71  SDL_SetTextureScaleMode(texture_.get(), linear_interpolation ? SDL_SCALEMODE_LINEAR : SDL_SCALEMODE_NEAREST);
72 
73  size_ = {surf->w, surf->h};
74 
75  finalize();
76 }
77 
78 texture::texture(int width, int height, SDL_TextureAccess access)
79  : texture_()
80 {
81  reset(width, height, access);
82 }
83 
85 {
86  set_blend_mode(SDL_BLENDMODE_BLEND);
87 }
88 
89 uint32_t texture::get_format() const
90 {
91  if(texture_) {
92  SDL_PropertiesID props = SDL_GetTextureProperties(texture_.get());
93  return SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_FORMAT_NUMBER, 0);
94  } else {
95  return SDL_PIXELFORMAT_UNKNOWN;
96  }
97 }
98 
100 {
101  if(texture_) {
102  SDL_PropertiesID props = SDL_GetTextureProperties(texture_.get());
103  return SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_ACCESS_NUMBER, 0);
104  } else {
105  return -1;
106  }
107 }
108 
110 {
111  if(texture_) {
112  SDL_PropertiesID props = SDL_GetTextureProperties(texture_.get());
113  return {
114  static_cast<int>(SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_WIDTH_NUMBER, 0)),
115  static_cast<int>(SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_HEIGHT_NUMBER, 0))
116  };
117  } else {
118  return {0, 0};
119  }
120 }
121 
122 void texture::set_src(const rect& r)
123 {
124  rect dsrc = r.intersect(rect{{0, 0}, size_});
125  point rsize = get_raw_size();
126  if (draw_size() == rsize) {
127  src_ = dsrc;
128  } else {
129  src_ = rect {
130  (dsrc.x * rsize.x) / size_.x,
131  (dsrc.y * rsize.y) / size_.y,
132  (dsrc.w * rsize.x) / size_.x,
133  (dsrc.h * rsize.y) / size_.y
134  };
135  }
136  has_src_ = true;
137 }
138 
140 {
141  rect max = {{0, 0}, get_raw_size()};
142  src_ = r.intersect(max);
143  has_src_ = true;
144 }
145 
146 void texture::set_alpha_mod(uint8_t alpha)
147 {
148  if (texture_) {
149  SDL_SetTextureAlphaMod(texture_.get(), alpha);
150  }
151 }
152 
153 uint8_t texture::get_alpha_mod() const
154 {
155  if (!texture_) {
156  return 0;
157  }
158  uint8_t a;
159  SDL_GetTextureAlphaMod(texture_.get(), &a);
160  return a;
161 }
162 
164 {
165  set_color_mod(c.r, c.g, c.b);
166 }
167 
168 void texture::set_color_mod(uint8_t r, uint8_t g, uint8_t b)
169 {
170  if (texture_) {
171  SDL_SetTextureColorMod(texture_.get(), r, g, b);
172  }
173 }
174 
176 {
177  if (!texture_) {
178  return {0,0,0};
179  }
180  color_t c;
181  SDL_GetTextureColorMod(texture_.get(), &c.r, &c.g, &c.b);
182  return c;
183 }
184 
185 void texture::set_blend_mode(SDL_BlendMode b)
186 {
187  if (texture_) {
188  SDL_SetTextureBlendMode(texture_.get(), b);
189  }
190 }
191 
192 SDL_BlendMode texture::get_blend_mode() const
193 {
194  if (!texture_) {
195  return SDL_BLENDMODE_NONE;
196  }
197  SDL_BlendMode b;
198  SDL_GetTextureBlendMode(texture_.get(), &b);
199  return b;
200 }
201 
203 {
204  if(texture_) {
205  texture_.reset();
206  }
207  size_ = {0, 0};
208  has_src_ = false;
209 }
210 
211 void texture::reset(int width, int height, SDL_TextureAccess access)
212 {
213  // No-op if texture is null.
214  reset();
215 
216  SDL_Renderer* renderer = video::get_renderer();
217  if(!renderer) {
218  return;
219  }
220 
221  texture_.reset(SDL_CreateTexture(renderer, default_texture_format, access, width, height), &cleanup_texture);
222  if(!texture_) {
223  ERR_SDL << "When creating texture: " << SDL_GetError();
224  return;
225  }
226 
227  size_ = {width, height};
228  has_src_ = false;
229 
230  finalize();
231 }
232 
233 void texture::assign(SDL_Texture* t)
234 {
235  texture_.reset(t, &cleanup_texture);
236  size_ = get_raw_size();
237  has_src_ = false;
238 }
239 
240 texture::info::info(SDL_Texture* t)
241  : format(SDL_PIXELFORMAT_UNKNOWN)
242  , access(-1)
243  , size(0, 0)
244 {
245  if (t) {
246  SDL_PropertiesID props = SDL_GetTextureProperties(t);
247  format = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_FORMAT_NUMBER, 0);
248  access = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_ACCESS_NUMBER, 0);
249  size.x = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_WIDTH_NUMBER, 0);
250  size.y = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_HEIGHT_NUMBER, 0);
251  }
252 }
double t
Definition: astarsearch.cpp:63
double g
Definition: astarsearch.cpp:63
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:33
uint8_t get_alpha_mod() const
Definition: texture.cpp:153
rect src_
uninitialized by default.
Definition: texture.hpp:215
SDL_BlendMode get_blend_mode() const
Definition: texture.cpp:192
int get_access() const
The texture access mode.
Definition: texture.cpp:99
uint32_t get_format() const
The internal texture format.
Definition: texture.cpp:89
std::shared_ptr< SDL_Texture > texture_
Definition: texture.hpp:212
void set_blend_mode(SDL_BlendMode mode)
Blend mode.
Definition: texture.cpp:185
bool has_src_
true iff the source rect is valid
Definition: texture.hpp:214
void finalize()
Definition: texture.cpp:84
void reset()
Releases ownership of the managed texture and resets the ptr to null.
Definition: texture.cpp:202
void set_src(const rect &r)
Set the source region of the texture used for drawing operations.
Definition: texture.cpp:122
texture()=default
Default ctor.
point draw_size() const
The size of the texture in draw-space.
Definition: texture.hpp:120
point size_
Definition: texture.hpp:213
point get_raw_size() const
The raw internal texture size.
Definition: texture.cpp:109
void assign(SDL_Texture *t)
Replaces ownership of the managed texture with the given one.
Definition: texture.cpp:233
void set_alpha_mod(uint8_t alpha)
Alpha modifier.
Definition: texture.cpp:146
color_t get_color_mod() const
Definition: texture.cpp:175
void set_src_raw(const rect &r)
Set the source region of the texture used for drawing operations.
Definition: texture.cpp:139
void set_color_mod(uint8_t r, uint8_t g, uint8_t b)
Colour modifier.
Definition: texture.cpp:168
static SDL_Renderer * renderer()
Definition: draw.cpp:33
Standard logging facilities (interface).
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:81
SDL_Renderer * get_renderer()
Definition: video.cpp:681
surface surf
Image.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:51
Holds a 2D point.
Definition: point.hpp:25
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:49
rect intersect(const rect &r) const
Calculates the intersection of this rectangle and another; that is, the maximal rectangle that is con...
Definition: rect.cpp:92
uint32_t format
Definition: texture.hpp:71
point size
Definition: texture.hpp:73
info(SDL_Texture *t)
Definition: texture.cpp:240
mock_char c
#define ERR_SDL
Definition: texture.cpp:24
static lg::log_domain log_sdl("SDL")
#define b