FIFE  be64c707dea6b3250bd4355bf5c825d25920087d
renderbackend.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2019 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 
24 // 3rd party library includes
25 
26 // FIFE includes
27 // These includes are split up in two parts, separated by one empty line
28 // First block: files included from the FIFE root src directory
29 // Second block: files included from the same folder
30 #include "renderbackend.h"
31 #include "video/devicecaps.h"
32 
33 namespace FIFE {
34  RenderBackend::RenderBackend(const SDL_Color& colorkey):
35  m_window(NULL),
36  m_screen(NULL),
37  m_target(NULL),
38  m_compressimages(false),
39  m_useframebuffer(false),
40  m_usenpot(false),
41  m_isalphaoptimized(false),
42  m_iscolorkeyenabled(false),
43  m_colorkey(colorkey),
44  m_isMipmapping(false),
45  m_textureFilter(TEXTURE_FILTER_NONE),
46  m_maxAnisotropy(0),
47  m_monochrome(false),
48  m_isDepthBuffer(false),
49  m_alphaValue(0.3),
50  m_vSync(false),
51  m_isframelimit(false),
52  m_frame_start(0),
53  m_framelimit(60) {
54 
55  m_isbackgroundcolor = false;
56  m_backgroundcolor.r = 0;
57  m_backgroundcolor.g = 0;
58  m_backgroundcolor.b = 0;
59  }
60 
62  }
63 
65  SDL_QuitSubSystem(SDL_INIT_VIDEO);
66  SDL_Quit();
67  }
68 
70  if (m_isframelimit) {
71  m_frame_start = SDL_GetTicks();
72  }
73  }
74 
76  if (m_isframelimit) {
77  uint16_t frame_time = SDL_GetTicks() - m_frame_start;
78  const float frame_limit = 1000.0f/m_framelimit;
79  if (frame_time < frame_limit) {
80  SDL_Delay(static_cast<Uint32>(frame_limit) - frame_time);
81  }
82  }
83  }
84 
86  return m_screenMode;
87  }
88 
90  return m_screen->w;
91  }
92 
94  return m_screen->h;
95  }
96 
97  const Rect& RenderBackend::getArea() const {
98  static Rect r(0, 0, m_screen->w, m_screen->h);
99  return r;
100  }
101 
102  void RenderBackend::pushClipArea(const Rect& cliparea, bool clear) {
103  ClipInfo ci;
104  ci.r = cliparea;
105  ci.clearing = clear;
106  m_clipstack.push(ci);
107  setClipArea(cliparea, clear);
108  }
109 
111  assert(!m_clipstack.empty());
112  m_clipstack.pop();
113  if (m_clipstack.empty()) {
114  setClipArea(getArea(), false);
115  } else {
116  ClipInfo ci = m_clipstack.top();
117  // instead of using ci.clearing, we set it to false
118  // to avoid double clearing
119  setClipArea(ci.r, false);
120  }
121  }
122 
124  if (!m_clipstack.empty()) {
125  return m_clipstack.top().r;
126  } else {
127  return getArea();
128  }
129  }
130 
132  setClipArea(getArea(), true);
133  }
134 
136  m_textureFilter = filter;
137  }
138 
140  return m_textureFilter;
141  }
142 
144  m_isMipmapping = enabled;
145  }
146 
148  return m_isMipmapping;
149  }
150 
152  return m_maxAnisotropy;
153  }
154 
156  m_monochrome = enabled;
157  }
158 
160  return m_monochrome;
161  }
162 
164  m_isDepthBuffer = enabled;
165  }
166 
168  return m_isDepthBuffer;
169  }
170 
172  m_alphaValue = alpha;
173  }
174 
176  return m_alphaValue;
177  }
178 
179  void RenderBackend::setColorKeyEnabled(bool colorkeyenable) {
180  m_iscolorkeyenabled = colorkeyenable;
181  }
182 
184  return m_iscolorkeyenabled;
185  }
186 
187  void RenderBackend::setColorKey(const SDL_Color& colorkey) {
188  m_colorkey = colorkey;
189  }
190 
191  const SDL_Color& RenderBackend::getColorKey() const {
192  return m_colorkey;
193  }
194 
196  if (r != m_backgroundcolor.r || g != m_backgroundcolor.g || b != m_backgroundcolor.b) {
197  m_isbackgroundcolor = true;
198  m_backgroundcolor.r = r;
199  m_backgroundcolor.g = g;
200  m_backgroundcolor.b = b;
201  }
202  }
203 
205  setBackgroundColor(0,0,0);
206  }
207 
208  const SDL_PixelFormat& RenderBackend::getPixelFormat() const {
209  return m_rgba_format;
210  }
211 
213  m_vSync = vsync;
214  }
215 
217  return m_vSync;
218  }
219 
221  m_isframelimit = limited;
222  }
223 
225  return m_isframelimit;
226  }
227 
229  m_framelimit = framelimit;
230  }
231 
233  return m_framelimit;
234  }
235 
237  return m_screen;
238  }
239 
241  return m_target;
242  }
243 
244  Point RenderBackend::getBezierPoint(const std::vector<Point>& points, int32_t elements, float t) {
245  if (t < 0.0) {
246  return points[0];
247  } else if (t >= static_cast<double>(elements)) {
248  return points.back();
249  }
250 
251  // Interpolate
252  double px = 0.0;
253  double py = 0.0;
254  int32_t n = elements - 1;
255  double muk = 1.0;
256  double mu = static_cast<double>(t) / static_cast<double>(elements);
257  double munk = Mathd::Pow(1.0 - mu, static_cast<double>(n));
258  for (int32_t i = 0; i <= n; ++i) {
259  int32_t tmpn = n;
260  int32_t tmpi = i;
261  int32_t diffn = n - i;
262  double blend = muk * munk;
263  muk *= mu;
264  munk /= 1.0 - mu;
265  while (tmpn) {
266  blend *= static_cast<double>(tmpn);
267  tmpn--;
268  if (tmpi > 1) {
269  blend /= static_cast<double>(tmpi);
270  tmpi--;
271  }
272  if (diffn > 1) {
273  blend /= static_cast<double>(diffn);
274  diffn--;
275  }
276  }
277  px += static_cast<double>(points[i].x) * blend;
278  py += static_cast<double>(points[i].y) * blend;
279  }
280 
281  return Point(static_cast<int32_t>(px), static_cast<int32_t>(py));
282  }
283 
284  void RenderBackend::addControlPoints(const std::vector<Point>& points, std::vector<Point>& newPoints) {
285  if (points.empty()) {
286  return;
287  }
288 
289  int32_t n = points.size() - 1;
290  // min 2 points
291  if (n < 1) {
292  return;
293  }
294 
295  Point p;
296  // straight line
297  if (n == 1) {
298  newPoints.push_back(points[0]);
299  p.x = (2 * points[0].x + points[1].x) / 3;
300  p.y = (2 * points[0].y + points[1].y) / 3;
301  newPoints.push_back(p);
302  p.x = 2 * p.x - points[0].x;
303  p.y = 2 * p.y - points[0].y;
304  newPoints.push_back(p);
305  newPoints.push_back(points[1]);
306  return;
307  }
308 
309  // calculate x and y values
310  float* xrhs = new float[n];
311  float* yrhs = new float[n];
312  // first
313  xrhs[0] = points[0].x + 2 * points[1].x;
314  yrhs[0] = points[0].y + 2 * points[1].y;
315  // last
316  xrhs[n - 1] = (8 * points[n - 1].x + points[n].x) / 2.0;
317  yrhs[n - 1] = (8 * points[n - 1].y + points[n].y) / 2.0;
318  // rest
319  for (int32_t i = 1; i < n - 1; ++i) {
320  xrhs[i] = 4 * points[i].x + 2 * points[i + 1].x;
321  yrhs[i] = 4 * points[i].y + 2 * points[i + 1].y;
322  }
323 
324  float* x = new float[n];
325  float* y = new float[n];
326  float* xtmp = new float[n];
327  float* ytmp = new float[n];
328  float xb = 2.0;
329  float yb = 2.0;
330  x[0] = xrhs[0] / xb;
331  y[0] = yrhs[0] / yb;
332  // Decomposition and forward substitution.
333  for (int32_t i = 1; i < n; i++) {
334  xtmp[i] = 1 / xb;
335  ytmp[i] = 1 / yb;
336  xb = (i < n - 1 ? 4.0 : 3.5) - xtmp[i];
337  yb = (i < n - 1 ? 4.0 : 3.5) - ytmp[i];
338  x[i] = (xrhs[i] - x[i - 1]) / xb;
339  y[i] = (yrhs[i] - y[i - 1]) / yb;
340  }
341  // Backward substitution
342  for (int32_t i = 1; i < n; i++) {
343  x[n - i - 1] -= xtmp[n - i] * x[n - i];
344  y[n - i - 1] -= ytmp[n - i] * y[n - i];
345  }
346 
347  // start point
348  newPoints.push_back(points[0]);
349  for (int32_t i = 0; i < n - 1; ++i) {
350  p.x = x[i];
351  p.y = y[i];
352  newPoints.push_back(p);
353  p.x = 2 * points[i + 1].x - x[i + 1];
354  p.y = 2 * points[i + 1].y - y[i + 1];
355  newPoints.push_back(p);
356 
357  newPoints.push_back(points[i+1]);
358  }
359  p.x = x[n - 1];
360  p.y = y[n - 1];
361  newPoints.push_back(p);
362  p.x = (points[n].x + x[n - 1]) / 2;
363  p.y = (points[n].y + y[n - 1]) / 2;
364  newPoints.push_back(p);
365  // end point
366  newPoints.push_back(points[n]);
367 
368  delete[] xrhs;
369  delete[] yrhs;
370  delete[] x;
371  delete[] y;
372  delete[] xtmp;
373  delete[] ytmp;
374  }
375 }
SDL_Surface * m_target
virtual void setClipArea(const Rect &cliparea, bool clear)=0
Sets given clip area into image.
uint32_t getHeight() const
RenderBackend(const SDL_Color &colorkey)
Constructor.
void setColorKey(const SDL_Color &colorkey)
Sets the global colorkey to use for images.
void setMonochromeEnabled(bool enabled)
Enables or disables monochrome rendering.
const SDL_Color & getColorKey() const
Gets the global colorkey setting.
bool isColorKeyEnabled() const
Gets whether the colorkey feature is in use.
const ScreenMode & getCurrentScreenMode() const
Get current screen mode.
SDL_PixelFormat m_rgba_format
void setBackgroundColor(uint8_t r, uint8_t g, uint8_t b)
Set the background color.
void addControlPoints(const std::vector< Point > &points, std::vector< Point > &newPoints)
Helper that adds the control points for bezier curves.
bool isMonochromeEnabled() const
void setColorKeyEnabled(bool colorkeyenable)
Sets whether to use the colorkey feature.
bool isFrameLimitEnabled() const
Gets whether the frame limiter is in use.
void resetBackgroundColor()
Reset the background color to black.
unsigned char uint8_t
Definition: core.h:38
float getAlphaTestValue() const
PointType2D< int32_t > Point
Definition: point.h:195
static T Pow(T _base, T _exponent)
Definition: fife_math.h:262
const SDL_PixelFormat & getPixelFormat() const
Gets the current screen rgba format.
void pushClipArea(const Rect &cliparea, bool clear=true)
Pushes clip area to clip stack Clip areas define which area is drawn on screen.
virtual void startFrame()
Called when a new frame starts.
void setMipmappingEnabled(bool enabled)
Enables or disables the usage of mipmapping.
void setAlphaTestValue(float alpha)
Sets the value for alpha test.
void setFrameLimit(uint16_t framelimit)
Sets the frame limit.
int32_t getMaxAnisotropy() const
Gets max antisotropy for antisotropic filtering.
SDL_Surface * getScreenSurface()
Returns screen render surface.
virtual ~RenderBackend()
Destructor.
void setTextureFiltering(TextureFiltering filter)
Sets the texture filtering method.
void popClipArea()
Pops clip area from clip stack.
unsigned short uint16_t
Definition: core.h:39
SDL_Surface * m_screen
void setDepthBufferEnabled(bool enabled)
Enables or disables depth buffer rendering.
const Rect & getClipArea() const
Gets the current clip area.
SDL_Color m_backgroundcolor
virtual void endFrame()
Called when a frame is finished and ready to be displayed.
bool isVSyncEnabled() const
Gets whether VSync is in use.
void clearClipArea()
Clears any possible clip areas.
void setFrameLimitEnabled(bool limited)
Sets whether to use the frame limiter.
const Rect & getArea() const
SDL_Surface * getRenderTargetSurface()
Returns currently attached render surface.
TextureFiltering m_textureFilter
TextureFiltering
Definition: renderbackend.h:99
Point getBezierPoint(const std::vector< Point > &points, int32_t elements, float t)
Helper that returns an interpolated Point.
uint32_t getWidth() const
ScreenMode m_screenMode
void deinit()
Performs cleanup actions.
bool isDepthBufferEnabled() const
std::stack< ClipInfo > m_clipstack
unsigned int uint32_t
Definition: core.h:40
void setVSyncEnabled(bool vsync)
Sets whether to use VSync.
bool isMipmappingEnabled() const
uint16_t getFrameLimit() const
Gets the frame limit.
TextureFiltering getTextureFiltering() const