rolmodl
C++ API for the Simple Directmedia Library 2 (SDL2)
SWTex.cpp
1 #include "hpp/SWTex.hpp"
2 
3 #include <utility>
4 #include <cassert>
5 
6 #include "hpp/Geom.hpp"
7 #include "hpp/Base.hpp"
8 
9 namespace rolmodl {
10  using detail::throwOnErr;
11 
12  SWTex_Base::SWTex_Base() :
13  h_(nullptr)
14  {};
15  SWTex_Base::SWTex_Base(const geom::Size s, const pixelfmt::Id fmt) :
16  h_(SDL_CreateRGBSurfaceWithFormat(0, s.w, s.h, static_cast<int>(pixelfmt::bitSizeOf(fmt)), pixelfmt::id::unsafe::toSDLEnum(fmt)))
17  {
18  if (h_ == nullptr)
19  throw sdlexception();
20  }
21 
22  SWTex_Base::~SWTex_Base() noexcept {
23  if (h_ != nullptr)
24  SDL_FreeSurface(h_);
25  h_ = nullptr;
26  }
27 
28  SWTex_Base::SWTex_Base(SWTex_Base&& that) noexcept :
29  SWTex_Base()
30  {
31  swap(*this, that);
32  }
33  SWTex_Base& SWTex_Base::operator=(SWTex_Base&& that) noexcept {
34  swap(*this, that);
35  return *this;
36  }
37 
38  void swap(SWTex_Base& a, SWTex_Base& b) noexcept {
39  using std::swap;
40  swap(a.h_, b.h_);
41  }
42 
43  pixelfmt::Id SWTex_Base::fmtId() noexcept {
44  return pixelfmt::id::unsafe::fromSDLEnum(fmt().format);
45  }
46  pixelfmt::Id SWTex_Base::fmtId() const noexcept {
47  return pixelfmt::id::unsafe::fromSDLEnum(fmt().format);
48  }
49 
50  SDL_PixelFormat& SWTex_Base::fmt() noexcept {
51  return *unsafeRaw()->format;
52  }
53  SDL_PixelFormat& SWTex_Base::fmt() const noexcept {
54  return *unsafeRaw()->format;
55  }
56 
57  unsigned int SWTex_Base::pitch() noexcept {
58  return static_cast<unsigned int>(unsafeRaw()->pitch);
59  }
60  unsigned int SWTex_Base::pitch() const noexcept {
61  return static_cast<unsigned int>(unsafeRaw()->pitch);
62  }
63 
64  int SWTex_Base::w() noexcept {
65  return unsafeRaw()->w;
66  }
67  int SWTex_Base::w() const noexcept {
68  return unsafeRaw()->w;
69  }
70  int SWTex_Base::h() noexcept {
71  return unsafeRaw()->h;
72  }
73  int SWTex_Base::h() const noexcept {
74  return unsafeRaw()->h;
75  }
76 
77  bool SWTex_Base::mustLock() noexcept {
78  return SDL_MUSTLOCK(unsafeRaw()) == SDL_TRUE;
79  }
80  bool SWTex_Base::mustLock() const noexcept {
81  return SDL_MUSTLOCK(unsafeRaw()) == SDL_TRUE;
82  }
83 
84  // h_ can be nullptr from
85  // the private default constructor
86  // => its a rolmodl bug
87  // SDL
88  // => user should have handled the exception and not tried to use the lock
89  SDL_Surface* SWTex_Base::unsafeRaw() noexcept {
90  assert(h_ != nullptr);
91  return h_;
92  }
93  const SDL_Surface* SWTex_Base::unsafeRaw() const noexcept {
94  assert(h_ != nullptr);
95  return h_;
96  }
97 
98  uint32_t& SWTex_Base::unsafePoint(const geom::Pos p) noexcept {
99  return *reinterpret_cast<uint32_t*>(
100  static_cast<char*>(unsafeRawPixels()) +
101  static_cast<unsigned int>(p.y)*pitch() +
102  static_cast<unsigned int>(p.x)*fmt().BytesPerPixel
103  );
104  }
105  const uint32_t& SWTex_Base::unsafePoint(const geom::Pos p) const noexcept {
106  return *reinterpret_cast<const uint32_t*>(static_cast<const char*>(unsafeRawPixels()) + static_cast<unsigned int>(p.y)*pitch() + p.x);
107  }
108 
109  void* SWTex_Base::unsafeRawPixels() noexcept {
110  return unsafeRaw()->pixels;
111  }
112  const void* SWTex_Base::unsafeRawPixels() const noexcept {
113  return unsafeRaw()->pixels;
114  }
115 
116  SWTex_Base& SWTex_Base::drawPoint(const RGBA c, const geom::Pos p) noexcept {
117  // fixme: assumes little endian
118  const uint32_t mask = static_cast<uint32_t>((~0 << fmt().BitsPerPixel));
119 
120  uint32_t& val = unsafePoint(p);
121  val = (val & mask) | SDL_MapRGBA(&fmt(), c.r, c.g, c.b, c.a);
122 
123  return *this;
124  }
125  RGBA SWTex_Base::getPoint(const geom::Pos p) const noexcept {
126  RGBA c{};
127  SDL_GetRGBA(unsafePoint(p), &fmt(), &c.r, &c.g, &c.b, &c.a);
128 
129  return c;
130  }
131 
132 
133  SWTex::SWTex() :
134  SWTex_Base()
135  {}
136  SWTex::SWTex(const geom::Size s, const pixelfmt::Id fmt) :
137  SWTex_Base(s, fmt)
138  {
139  assert(!mustLock()); // fixme: assuming that new surfaces are always non-RLE
140  }
141  /*explicit*/ SWTex::SWTex(SWTex_RLE&& rle) noexcept :
142  SWTex_Base()
143  {
144  std::swap(h_, rle.h_); // note that this is not a move-constructor
145  throwOnErr(SDL_SetSurfaceRLE(unsafeRaw(), false));
146  }
147 
148  SWTex& SWTex::drawPoint(const RGBA c, const geom::Pos p) noexcept {
149  SWTex_Base::drawPoint(c, p);
150  return *this;
151  }
152  RGBA SWTex::getPoint(const geom::Pos p) const noexcept {
153  return SWTex_Base::getPoint(p);
154  }
155 
156 
157  SWTex_RLE::SWTex_RLE(const geom::Size s, const pixelfmt::Id fmt) :
158  SWTex_Base(s, fmt)
159  {
160  assert(!mustLock()); // fixme: assuming that new surfaces are always non-RLE
161  throwOnErr(SDL_SetSurfaceRLE(unsafeRaw(), true));
162  assert(mustLock()); // fixme: assuming that new surfaces are always non-RLE
163  }
164  /*explicit*/ SWTex_RLE::SWTex_RLE(SWTex&& nonRle) noexcept :
165  SWTex_Base()
166  {
167  std::swap(h_, nonRle.h_); // note that this is not a move-constructor
168  throwOnErr(SDL_SetSurfaceRLE(unsafeRaw(), true));
169  }
170 
171 
172  SWTex_RLELock::SWTex_RLELock() noexcept :
173  h_(nullptr)
174  {}
175  /*explicit*/ SWTex_RLELock::SWTex_RLELock(SWTex_RLE& t) :
176  h_(&t)
177  {
178  throwOnErr(SDL_LockSurface(t.unsafeRaw()));
179  }
180 
181  SWTex_RLELock::~SWTex_RLELock() noexcept {
182  if (h_ != nullptr)
183  SDL_UnlockSurface(h_->unsafeRaw());
184  h_ = nullptr;
185  }
186 
187  SWTex_RLELock::SWTex_RLELock(SWTex_RLELock&& that) noexcept :
188  SWTex_RLELock()
189  {
190  swap(*this, that);
191  }
192  SWTex_RLELock& SWTex_RLELock::operator=(SWTex_RLELock&& that) noexcept {
193  swap(*this, that);
194  return *this;
195  }
196 
197  void swap(SWTex_RLELock& a, SWTex_RLELock& b) noexcept {
198  using std::swap;
199  swap(a.h_, b.h_);
200  }
201 
202  SWTex_RLELock& SWTex_RLELock::drawPoint(const RGBA c, const geom::Pos p) noexcept {
203  h_->drawPoint(c, p);
204  return *this;
205  }
206  RGBA SWTex_RLELock::getPoint(const geom::Pos p) const noexcept {
207  return h_->getPoint(p);
208  }
209 
210 
211  SWTex& Win_SW::swtex() {
212  if (tex.h_ != nullptr)
213  return tex;
214 
215  SDL_Surface* res = SDL_GetWindowSurface(unsafeRaw());
216  if (res == nullptr)
217  throw sdlexception();
218  tex.h_ = res;
219  assert(!tex.mustLock()); // fixme
220 
221  return tex;
222  }
223  Win_SW::~Win_SW() noexcept {
224  tex.h_ = nullptr; // don't free the SW tex
225  }
226 }
rolmodl::detail::throwOnErr
int throwOnErr(const int code)
Throw a rolmodl::sdlexception if code < 0.
Definition: Base.cpp:370
utility
rolmodl::Win_Base::unsafeRaw
SDL_Window * unsafeRaw() noexcept
Get the underlying SDL_Window*. Unsafe because this value might be nullptr and using it with some SDL...
Definition: Win.cpp:81
Geom.hpp
rolmodl
Main namespace.
Definition: Base.cpp:7
std::swap
T swap(T... args)
cassert
Base.hpp
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
rolmodl::Ren::unsafeRaw
SDL_Renderer * unsafeRaw() noexcept
Get the underlying SDL_Renderer*. Unsafe because this value might be nullptr and using it with some S...
Definition: Ren.cpp:86