rolmodl
C++ API for the Simple Directmedia Library 2 (SDL2)
Tex.cpp
1 #include "hpp/Tex.hpp"
2 
3 #include <utility>
4 #include <cassert>
5 
6 #include "hpp/Ren.hpp"
7 
8 namespace rolmodl {
9  using detail::throwOnErr;
10 
11  Tex::Tex() noexcept :
12  h_(nullptr)
13  {}
14  Tex::Tex(Ren& r, const pixelfmt::Id fmt, const int access, const geom::Size s) :
15  h_(SDL_CreateTexture(r.unsafeRaw(), pixelfmt::id::unsafe::toSDLEnum(fmt), access, s.w, s.h))
16  {
17  if (h_ == nullptr)
18  throw sdlexception();
19  }
20 
21  Tex::~Tex() noexcept {
22  if (h_ != nullptr)
23  SDL_DestroyTexture(h_);
24  h_ = nullptr;
25  }
26 
27  Tex::Tex(Tex&& that) noexcept :
28  Tex()
29  {
30  swap(*this, that);
31  }
32  Tex& Tex::operator=(Tex&& that) noexcept {
33  swap(*this, that);
34  return *this;
35  }
36 
37  void swap(Tex& a, Tex& b) noexcept {
38  using std::swap;
39  swap(a.h_, b.h_);
40  }
41 
42  BlendMode Tex::getBlendMode() {
43  SDL_BlendMode tmp = SDL_BLENDMODE_NONE;
44  throwOnErr(SDL_GetTextureBlendMode(unsafeRaw(), &tmp));
46  }
47  void Tex::setBlendMode(const BlendMode m) {
48  throwOnErr(SDL_SetTextureBlendMode(unsafeRaw(), blendMode::unsafe::toSDLEnum(m)));
49  }
50 
51  uint8_t Tex::getAlphaMod() {
52  uint8_t res = 0;
53  throwOnErr(SDL_GetTextureAlphaMod(unsafeRaw(), &res));
54  return res;
55  }
56  void Tex::setAlphaMod(const uint8_t i) {
57  throwOnErr(SDL_SetTextureAlphaMod(unsafeRaw(), i));
58  }
59 
60  RGB Tex::getRGBMod() {
61  RGB res{};
62  throwOnErr(SDL_GetTextureColorMod(unsafeRaw(), &res.r, &res.g, &res.b));
63  return res;
64  }
65  void Tex::setRGBMod(const RGB i) {
66  throwOnErr(SDL_SetTextureColorMod(unsafeRaw(), i.r, i.g, i.b));
67  }
68 
69  TextureInfo Tex::query() {
70  uint32_t format = 0;
71  int access = 0;
72 
73  TextureInfo res{};
74  throwOnErr(SDL_QueryTexture(unsafeRaw(), &format, &access, &res.size.w, &res.size.h));
75 
76  res.fmt = pixelfmt::id::unsafe::fromSDLEnum(format);
77  res.type = textureType::unsafe::fromSDLEnum(access);
78  return res;
79  }
80 
81  // h_ can be nullptr from
82  // the private default constructor
83  // => its a rolmodl bug
84  // SDL
85  // => user should have handled the exception and not tried to use the texture
86  SDL_Texture* Tex::unsafeRaw() noexcept {
87  assert(h_ != nullptr);
88  return h_;
89  }
90  const SDL_Texture* Tex::unsafeRaw() const noexcept {
91  assert(h_ != nullptr);
92  return h_;
93  }
94 
95  StaticTex::StaticTex(Ren& r, const pixelfmt::Id fmt, const geom::Size s) :
96  Tex(r, fmt, SDL_TEXTUREACCESS_STATIC, s) {}
97 
98 
99  LockTex::LockTex() noexcept :
100  Tex(),
101  format_(pixelfmt::Id::unknown)
102  {}
103  LockTex::LockTex(Ren& r, const pixelfmt::Id fmt, const geom::Size s) :
104  Tex(r, fmt, SDL_TEXTUREACCESS_STREAMING, s),
105  format_(fmt)
106  {}
107 
108  pixelfmt::Id LockTex::format() const noexcept {
109  assert(h_ != nullptr); // catch errors early
110  return format_;
111  }
112 
113 
114  RenTex::RenTex(Ren& r, const pixelfmt::Id fmt, const geom::Size s) :
115  Tex(r, fmt, SDL_TEXTUREACCESS_TARGET, s) {}
116 
117 
118  TexLock::TexLock() noexcept :
119  t_(nullptr),
120  h_(nullptr),
121  pitch_(0)
122  {}
123  TexLock::TexLock(LockTex& tex, const SDL_Rect* r) :
124  t_(&tex),
125  h_(nullptr),
126  pitch_(0)
127  {
128  int pitch = 0;
129  throwOnErr(SDL_LockTexture(tex.unsafeRaw(), r, &h_, &pitch));
130  pitch_ = static_cast<unsigned int>(pitch);
131  }
132  TexLock::TexLock(LockTex& tex, const SDL_Rect r) :
133  TexLock(tex, &r) {}
134 
135  /*explicit*/ TexLock::TexLock(LockTex& tex) :
136  TexLock(tex, nullptr) {}
137  TexLock::TexLock(LockTex& tex, const geom::RectWH r) :
138  TexLock(tex, r.sdl()) {}
139  TexLock::TexLock(LockTex& tex, const geom::RectXY r) :
140  TexLock(tex, r.wh()) {}
141 
142  TexLock::~TexLock() noexcept {
143  if (h_ != nullptr) {
144  assert(t_ != nullptr);
145  SDL_UnlockTexture(t_->unsafeRaw());
146  }
147 
148  t_ = nullptr;
149  h_ = nullptr;
150  pitch_ = 0;
151  }
152 
153  TexLock::TexLock(TexLock&& that) noexcept :
154  TexLock()
155  {
156  swap(*this, that);
157  }
158  TexLock& TexLock::operator=(TexLock&& that) noexcept {
159  swap(*this, that);
160  return *this;
161  }
162 
163  void swap(TexLock& a, TexLock& b) noexcept {
164  using std::swap;
165  swap(a.t_, b.t_);
166  swap(a.h_, b.h_);
167  swap(a.pitch_, b.pitch_);
168  }
169 
170  TexLock& TexLock::drawPoint(const RGBA c, const geom::Pos p) noexcept {
171  const SDL_PixelFormat f = pixelfmt::PixelFmtStorage::instance().get(t_->format());
172 
173  // fixme: assumes little endian
174  const uint32_t mask = static_cast<uint32_t>((~0 << f.BitsPerPixel));
175 
176  uint32_t& val = unsafePoint(p);
177  val = (val & mask) | SDL_MapRGBA(&f, c.r, c.g, c.b, c.a);
178 
179  return *this;
180  }
181  RGBA TexLock::getPoint(const geom::Pos p) const noexcept {
182  const SDL_PixelFormat f = pixelfmt::PixelFmtStorage::instance().get(t_->format());
183 
184  RGBA c{};
185  SDL_GetRGBA(unsafePoint(p), &f, &c.r, &c.g, &c.b, &c.a);
186 
187  return c;
188  }
189 
190  uint32_t& TexLock::unsafePoint(const geom::Pos p) noexcept {
191  return *reinterpret_cast<uint32_t*>(
192  static_cast<char*>(unsafeRaw()) +
193  static_cast<unsigned int>(p.y)*pitch_ +
194  static_cast<unsigned int>(p.x)*pixelfmt::byteSizeOf(t_->format())
195  );
196  }
197  const uint32_t& TexLock::unsafePoint(const geom::Pos p) const noexcept {
198  return *reinterpret_cast<const uint32_t*>(static_cast<const char*>(unsafeRaw()) + static_cast<unsigned int>(p.y)*pitch_ + p.x);
199  }
200 
201  // h_ can be nullptr from
202  // the private default constructor
203  // => its a rolmodl bug
204  // SDL
205  // => user should have handled the exception and not tried to use the lock
206  void* TexLock::unsafeRaw() noexcept {
207  assert(h_ != nullptr);
208  return h_;
209  }
210  const void* TexLock::unsafeRaw() const noexcept {
211  assert(h_ != nullptr);
212  return h_;
213  }
214 }
rolmodl::detail::throwOnErr
int throwOnErr(const int code)
Throw a rolmodl::sdlexception if code < 0.
Definition: Base.cpp:370
rolmodl::blendMode::unsafe::fromSDLEnum
constexpr BlendMode fromSDLEnum(const SDL_BlendMode m) noexcept
Convert an SDL_BlendMode value to a rolmodl::BlendMode value.
Definition: Ren.hpp:49
utility
rolmodl::blendMode::unsafe::toSDLEnum
constexpr SDL_BlendMode toSDLEnum(const BlendMode m) noexcept
Convert a rolmodl::BlendMode value to an SDL_BlendMode value.
Definition: Ren.hpp:60
Ren.hpp
rolmodl
Main namespace.
Definition: Base.cpp:7
std::swap
T swap(T... args)
rolmodl::BlendMode
BlendMode
Describes how colors are combined when rendering twice to the same place.
Definition: Ren.hpp:21
cassert
rolmodl::sys::Id
Id
OS type enum.
Definition: Base.hpp:28
rolmodl::sys::id
Id id() noexcept
Get id of the OS on which the code is running. May differ from whatever operating system the code was...
Definition: Base.cpp:14