FIFE  be64c707dea6b3250bd4355bf5c825d25920087d
renderbackendsdl.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 #include <SDL.h>
26 
27 // FIFE includes
28 // These includes are split up in two parts, separated by one empty line
29 // First block: files included from the FIFE root src directory
30 // Second block: files included from the same folder
31 #include "util/base/exception.h"
32 #include "util/math/fife_math.h"
33 #include "util/log/logger.h"
34 #include "video/devicecaps.h"
35 
36 #include "renderbackendsdl.h"
37 #include "sdlimage.h"
38 #include "SDL_image.h"
39 
40 namespace FIFE {
44  static Logger _log(LM_VIDEO);
45 
46  RenderBackendSDL::RenderBackendSDL(const SDL_Color& colorkey) :
47  RenderBackend(colorkey),
48  m_renderer(NULL) {
49  }
50 
52  SDL_DestroyRenderer(m_renderer);
53  SDL_DestroyWindow(m_window);
54  deinit();
55  }
56 
57  const std::string& RenderBackendSDL::getName() const {
58  static std::string backend_name = "SDL";
59  return backend_name;
60  }
61 
62  void RenderBackendSDL::init(const std::string& driver) {
63  if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
64  throw SDLException(SDL_GetError());
65  }
66  if (driver != "") {
67  if (SDL_VideoInit(driver.c_str()) < 0) {
68  throw SDLException(SDL_GetError());
69  }
70  }
71  }
72 
74  SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, 255);
75  SDL_RenderClear(m_renderer);
76  }
77 
78  void RenderBackendSDL::createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon){
79  setScreenMode(mode);
80  if (m_window) {
81  if (icon != "") {
82  SDL_Surface *img = IMG_Load(icon.c_str());
83  if (img != NULL) {
84  SDL_SetWindowIcon(m_window, img);
85  SDL_FreeSurface(img);
86  }
87  }
88  SDL_SetWindowTitle(m_window, title.c_str());
89  }
90  }
91 
93  uint16_t width = mode.getWidth();
94  uint16_t height = mode.getHeight();
95  uint16_t bitsPerPixel = mode.getBPP();
96  uint32_t flags = mode.getSDLFlags();
97  // in case of recreating
98  if (m_window) {
99  SDL_DestroyRenderer(m_renderer);
100  SDL_DestroyWindow(m_window);
101  m_screen = NULL;
102  }
103  // create window
104  uint8_t displayIndex = mode.getDisplay();
105  if (mode.isFullScreen()) {
106  m_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), width, height, flags | SDL_WINDOW_SHOWN);
107  } else {
108  m_window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), width, height, flags | SDL_WINDOW_SHOWN);
109  }
110 
111  if (!m_window) {
112  throw SDLException(SDL_GetError());
113  }
114  // make sure the window have the right settings
115  SDL_DisplayMode displayMode;
116  displayMode.format = mode.getFormat();
117  displayMode.w = width;
118  displayMode.h = height;
119  displayMode.refresh_rate = mode.getRefreshRate();
120  if (SDL_SetWindowDisplayMode(m_window, &displayMode) != 0) {
121  throw SDLException(SDL_GetError());
122  }
123 
124  // create renderer with given flags
125  flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
126  if (m_vSync) {
127  flags |= SDL_RENDERER_PRESENTVSYNC;
128  }
129  m_renderer = SDL_CreateRenderer(m_window, mode.getRenderDriverIndex(), flags);
130  if (!m_renderer) {
131  throw SDLException(SDL_GetError());
132  }
133  // set texture filtering
135  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
136  } else if (m_textureFilter != TEXTURE_FILTER_NONE) {
137  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
138  } else {
139  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
140  }
141  // enable alpha blending
142  SDL_SetRenderDrawBlendMode(m_renderer, SDL_BLENDMODE_BLEND);
143 
144  // set the window surface as main surface, not really needed anymore
145  m_screen = SDL_GetWindowSurface(m_window);
146  m_target = m_screen;
147  if (!m_screen) {
148  throw SDLException(SDL_GetError());
149  }
150 
151  FL_LOG(_log, LMsg("RenderBackendSDL")
152  << "Videomode " << width << "x" << height
153  << " at " << int32_t(bitsPerPixel) << " bpp with " << displayMode.refresh_rate << " Hz");
154 
155  // this is needed, otherwise we would have screen pixel formats which will not work with
156  // our texture generation. 32 bit surfaces to BitsPerPixel texturen.
157  m_rgba_format = *(m_screen->format);
158  if (bitsPerPixel != 16) {
159  m_rgba_format.format = SDL_PIXELFORMAT_RGBA8888;
160  m_rgba_format.BitsPerPixel = 32;
161  } else {
162  m_rgba_format.format = SDL_PIXELFORMAT_RGBA4444;
163  m_rgba_format.BitsPerPixel = 16;
164  }
165  m_rgba_format.Rmask = RMASK;
166  m_rgba_format.Gmask = GMASK;
167  m_rgba_format.Bmask = BMASK;
168  m_rgba_format.Amask = AMASK;
169 
170  //update the screen mode with the actual flags used
171  m_screenMode = mode;
172  }
173 
176  }
177 
179  SDL_RenderPresent(m_renderer);
181  }
182 
184  return new SDLImage(loader);
185  }
186 
187  Image* RenderBackendSDL::createImage(const std::string& name, IResourceLoader* loader) {
188  return new SDLImage(name, loader);
189  }
190 
191  Image* RenderBackendSDL::createImage(SDL_Surface* surface) {
192  return new SDLImage(surface);
193  }
194 
195  Image* RenderBackendSDL::createImage(const std::string& name, SDL_Surface* surface) {
196  return new SDLImage(name, surface);
197  }
198 
200  return new SDLImage(data, width, height);
201  }
202 
203  Image* RenderBackendSDL::createImage(const std::string& name, const uint8_t* data, uint32_t width, uint32_t height) {
204  return new SDLImage(name, data, width, height);
205  }
206 
208  SDLException("Lighting not available under SDL");
209  }
210 
212  return 0;
213  }
214 
215  void RenderBackendSDL::setLighting(float red, float green, float blue) {
216  }
217 
219  }
220 
222  }
223 
224  void RenderBackendSDL::changeBlending(int32_t scr, int32_t dst){
225  }
226 
228  }
229 
230  void RenderBackendSDL::addImageToArray(uint32_t id, const Rect& rec, float const* st, uint8_t alpha, uint8_t const* rgba) {
231  }
232 
233  void RenderBackendSDL::changeRenderInfos(RenderDataType type, uint16_t elements, int32_t src, int32_t dst, bool light, bool stentest, uint8_t stenref, GLConstants stenop, GLConstants stenfunc, OverlayType otype) {
234  }
235 
236  bool RenderBackendSDL::putPixel(int32_t x, int32_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
237  SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
238  if (SDL_RenderDrawPoint(m_renderer, x, y) == 0) {
239  return true;
240  }
241  return false;
242  }
243 
244  void RenderBackendSDL::drawLine(const Point& p1, const Point& p2, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
245  SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
246  SDL_RenderDrawLine(m_renderer, p1.x, p1.y, p2.x, p2.y);
247  }
248 
249  void RenderBackendSDL::drawThickLine(const Point& p1, const Point& p2, uint8_t width, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
250  float xDiff = p2.x - p1.x;
251  float yDiff = p2.y - p1.y;
252  float halfW = static_cast<float>(width) / 2.0;
253  float angle = Mathf::ATan2(yDiff, xDiff) * (180.0 / Mathf::pi()) + 90.0;
254  if (angle < 0.0) {
255  angle += 360.0;
256  } else if (angle > 360.0) {
257  angle -= 360.0;
258  }
259  angle *= Mathf::pi() / 180.0;
260  float cornerX = halfW * Mathf::Cos(angle);
261  float cornerY = halfW * Mathf::Sin(angle);
262  int32_t yMax = p1.y;
263  int32_t yMin = p1.y;
264 
265  std::vector<Point> points;
266  Point p(p1.x + cornerX, p1.y + cornerY);
267  yMax = std::max(yMax, p.y);
268  yMin = std::min(yMin, p.y);
269  points.push_back(p);
270  p.x = p2.x + cornerX;
271  p.y = p2.y + cornerY;
272  yMax = std::max(yMax, p.y);
273  yMin = std::min(yMin, p.y);
274  points.push_back(p);
275  p.x = p2.x - cornerX;
276  p.y = p2.y - cornerY;
277  yMax = std::max(yMax, p.y);
278  yMin = std::min(yMin, p.y);
279  points.push_back(p);
280  p.x = p1.x - cornerX;
281  p.y = p1.y - cornerY;
282  yMax = std::max(yMax, p.y);
283  yMin = std::min(yMin, p.y);
284  points.push_back(p);
285 
286  // scan-line fill algorithm
287  int32_t y = yMin;
288  int32_t n = points.size();
289  for (; y <= yMax; ++y) {
290  std::vector<int32_t> xs;
291  int32_t j = n - 1;
292  for (int32_t i = 0; i < n; j = i++) {
293  if ((points[i].y < y && y <= points[j].y) || (points[j].y < y && y <= points[i].y)) {
294  int32_t x = static_cast<int32_t>(points[i].x + static_cast<float>(y - points[i].y) / static_cast<float>(points[j].y - points[i].y) * static_cast<float>(points[j].x - points[i].x));
295  xs.push_back(x);
296  for (int32_t k = xs.size() - 1; k && xs[k-1] > xs[k]; --k) {
297  std::swap(xs[k-1], xs[k]);
298  }
299  }
300  }
301 
302  for (int32_t i = 0; i < xs.size(); i += 2) {
303  int32_t x1 = xs[i];
304  int32_t x2 = xs[i+1];
305  // vertical line
306  while (x1 <= x2) {
307  putPixel(x1, y, r, g, b, a);
308  ++x1;
309  }
310  }
311  }
312  }
313 
314  void RenderBackendSDL::drawPolyLine(const std::vector<Point>& points, uint8_t width, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
315  if (points.size() < 2) {
316  return;
317  }
318 
319  std::vector<Point>::const_iterator it = points.begin();
320  Point old = *it;
321  ++it;
322  if (width > 1) {
323  for (; it != points.end(); ++it) {
324  drawThickLine(old, *it, width, r, g, b, a);
325  drawFillCircle(old, width / 2, r, g, b, a);
326  old = *it;
327  }
328  drawFillCircle(old, width / 2, r, g, b, a);
329  } else {
330  for (; it != points.end(); ++it) {
331  drawLine(old, *it, r, g, b, a);
332  old = *it;
333  }
334  }
335  }
336 
337  void RenderBackendSDL::drawBezier(const std::vector<Point>& points, int32_t steps, uint8_t width, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
338  if (points.size() < 2) {
339  return;
340  }
341  int32_t elements = points.size();
342  if (elements < 3 || steps < 2) {
343  return;
344  }
345 
346  bool thick = width > 1;
347  float step = 1.0 / static_cast<float>(steps-1);
348  float t = 0.0;
349  Point old = getBezierPoint(points, elements+1, t);
350  if (thick) {
351  for (int32_t i = 0; i <= (elements*steps); ++i) {
352  t += step;
353  Point next = getBezierPoint(points, elements, t);
354  drawThickLine(old, next, width, r, g, b, a);
355  drawFillCircle(old, width / 2, r, g, b, a);
356  old = next;
357  }
358  drawFillCircle(old, width / 2, r, g, b, a);
359  } else {
360  for (int32_t i = 0; i <= (elements*steps); ++i) {
361  t += step;
362  Point next = getBezierPoint(points, elements, t);
363  drawLine(old, next, r, g, b, a);
364  old = next;
365  }
366  }
367  }
368 
369  void RenderBackendSDL::drawTriangle(const Point& p1, const Point& p2, const Point& p3, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
370  SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
371  SDL_RenderDrawLine(m_renderer, p1.x, p1.y, p2.x, p2.y);
372  SDL_RenderDrawLine(m_renderer, p2.x, p2.y, p3.x, p3.y);
373  SDL_RenderDrawLine(m_renderer, p3.x, p1.y, p1.x, p1.y);
374  }
375 
377  SDL_Rect rect;
378  rect.x = p.x;
379  rect.y = p.y;
380  rect.w = w;
381  rect.h = h;
382  SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
383  SDL_RenderDrawRect(m_renderer, &rect);
384  }
385 
387  SDL_Rect rect;
388  rect.x = p.x;
389  rect.y = p.y;
390  rect.w = w;
391  rect.h = h;
392  SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
393  SDL_RenderFillRect(m_renderer, &rect);
394  }
395 
396  void RenderBackendSDL::drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
397  fillRectangle(p1, static_cast<uint16_t>(p3.x-p1.x), static_cast<uint16_t>(p3.y-p1.y), r, g, b, a);
398  }
399 
400  void RenderBackendSDL::drawVertex(const Point& p, const uint8_t size, uint8_t r, uint8_t g, uint8_t b, uint8_t a){
401  Point p1 = Point(p.x-size, p.y+size);
402  Point p2 = Point(p.x+size, p.y+size);
403  Point p3 = Point(p.x+size, p.y-size);
404  Point p4 = Point(p.x-size, p.y-size);
405 
406  SDL_SetRenderDrawColor(m_renderer, r, g, b, a);
407  SDL_RenderDrawLine(m_renderer, p1.x, p1.y, p2.x, p2.y);
408  SDL_RenderDrawLine(m_renderer, p2.x, p2.y, p3.x, p3.y);
409  SDL_RenderDrawLine(m_renderer, p3.x, p3.y, p4.x, p4.y);
410  SDL_RenderDrawLine(m_renderer, p4.x, p4.y, p1.x, p1.y);
411  }
412 
414  // Midpoint Circle Algorithm
415  int32_t x = radius;
416  int32_t y = 0;
417  int32_t radiusError = 1-x;
418 
419  while(x >= y) {
420  putPixel(x + p.x, y + p.y, r, g, b, a);
421  putPixel(y + p.x, x + p.y, r, g, b, a);
422  putPixel(-x + p.x, y + p.y, r, g, b, a);
423  putPixel(-y + p.x, x + p.y, r, g, b, a);
424  putPixel(-x + p.x, -y + p.y, r, g, b, a);
425  putPixel(-y + p.x, -x + p.y, r, g, b, a);
426  putPixel(x + p.x, -y + p.y, r, g, b, a);
427  putPixel(y + p.x, -x + p.y, r, g, b, a);
428  y++;
429  if (radiusError < 0) {
430  radiusError += 2 * y + 1;
431  } else {
432  x--;
433  radiusError += 2 * (y - x + 1);
434  }
435  }
436  }
437 
439  float rad = static_cast<float>(radius);
440  for (float dy = 1; dy <= r; dy += 1.0) {
441  float dx = Mathf::Floor(Mathf::Sqrt((2.0 * rad * dy) - (dy * dy)));
442  int32_t x = p.x - dx;
443  for (; x <= p.x + dx; x++) {
444  putPixel(x, p.y + rad - dy, r, g, b, a);
445  putPixel(x, p.y - rad + dy, r, g, b, a);
446  }
447  }
448  }
449 
450  void RenderBackendSDL::drawCircleSegment(const Point& p, uint32_t radius, int32_t sangle, int32_t eangle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
451  const float step = Mathf::twoPi() / 360;
452  int32_t s = (sangle + 360) % 360;
453  int32_t e = (eangle + 360) % 360;
454  if (e == 0) {
455  e = 360;
456  }
457  if (s == e) {
458  return;
459  }
460 
461  float angle = static_cast<float>(s) * step;
462  Point oldPoint(radius * Mathf::Cos(angle) + p.x, radius * Mathf::Sin(angle) + p.y);
463  for (;s <= e; ++s, angle += step) {
464  Point newPoint(radius * Mathf::Cos(angle) + p.x, radius * Mathf::Sin(angle) + p.y);
465  drawLine(oldPoint, newPoint, r, g, b, a);
466  oldPoint = newPoint;
467  }
468  }
469 
470  void RenderBackendSDL::drawFillCircleSegment(const Point& p, uint32_t radius, int32_t sangle, int32_t eangle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
471  const float step = Mathf::twoPi() / 360;
472  int32_t s = (sangle + 360) % 360;
473  int32_t e = (eangle + 360) % 360;
474  if (e == 0) {
475  e = 360;
476  }
477  if (s == e) {
478  return;
479  }
480 
481  std::vector<Point> points;
482  points.push_back(p);
483  int32_t yMax = p.y;
484  int32_t yMin = p.y;
485  float angle = static_cast<float>(s) * step;
486  for (;s <= e; ++s, angle += step) {
487  Point newPoint(radius * Mathf::Cos(angle) + p.x, radius * Mathf::Sin(angle) + p.y);
488  yMax = std::max(yMax, newPoint.y);
489  yMin = std::min(yMin, newPoint.y);
490  points.push_back(newPoint);
491  }
492  // add end point (again)
493  angle = static_cast<float>(e) * step;
494  Point newPoint(radius * Mathf::Cos(angle) + p.x, radius * Mathf::Sin(angle) + p.y);
495  points.push_back(newPoint);
496  yMax = std::max(yMax, newPoint.y);
497  yMin = std::min(yMin, newPoint.y);
498 
499  // scan-line fill algorithm
500  int32_t y = yMin;
501  int32_t n = points.size();
502  for (; y <= yMax; ++y) {
503  std::vector<int32_t> xs;
504  int32_t j = n - 1;
505  for (int32_t i = 0; i < n; j = i++) {
506  if ((points[i].y < y && y <= points[j].y) || (points[j].y < y && y <= points[i].y)) {
507  int32_t x = static_cast<int32_t>(points[i].x + static_cast<float>(y - points[i].y) / static_cast<float>(points[j].y - points[i].y) * static_cast<float>(points[j].x - points[i].x));
508  xs.push_back(x);
509  for (int32_t k = xs.size() - 1; k && xs[k-1] > xs[k]; --k) {
510  std::swap(xs[k-1], xs[k]);
511  }
512  }
513  }
514 
515  for (int32_t i = 0; i < xs.size(); i += 2) {
516  int32_t x1 = xs[i];
517  int32_t x2 = xs[i+1];
518  // vertical line
519  while (x1 <= x2) {
520  putPixel(x1, y, r, g, b, a);
521  ++x1;
522  }
523  }
524  }
525  }
526 
527  void RenderBackendSDL::drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int32_t subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue) {
528  }
529 
531  }
532 
534  }
535 
536  void RenderBackendSDL::captureScreen(const std::string& filename) {
537  if(m_screen) {
538  const uint32_t swidth = getWidth();
539  const uint32_t sheight = getHeight();
540 
541  SDL_Surface* surface = SDL_CreateRGBSurface(0, swidth, sheight, 24,
543 
544  if(!surface) {
545  return;
546  }
547 
548  SDL_BlitSurface(m_screen, NULL, surface, NULL);
549 
550  Image::saveAsPng(filename, *surface);
551  SDL_FreeSurface(surface);
552  }
553  }
554 
555  void RenderBackendSDL::captureScreen(const std::string& filename, uint32_t width, uint32_t height) {
556  if(m_screen) {
557  const uint32_t swidth = getWidth();
558  const uint32_t sheight = getHeight();
559  const bool same_size = (width == swidth && height == sheight);
560 
561  if (width < 1 || height < 1) {
562  return;
563  }
564 
565  if (same_size) {
566  captureScreen(filename);
567  return;
568  }
569  // create source surface
570  SDL_Surface* src = SDL_CreateRGBSurface(0, swidth, sheight, 32,
571  RMASK, GMASK, BMASK, AMASK);
572 
573  if(!src) {
574  return;
575  }
576  // copy screen suface to source surface
577  SDL_BlitSurface(m_screen, NULL, src, NULL);
578  // create destination surface
579  SDL_Surface* dst = SDL_CreateRGBSurface(0, width, height, 32,
580  RMASK, GMASK, BMASK, AMASK);
581 
582  uint32_t* src_pointer = static_cast<uint32_t*>(src->pixels);
583  uint32_t* src_help_pointer = src_pointer;
584  uint32_t* dst_pointer = static_cast<uint32_t*>(dst->pixels);
585 
586  int32_t x, y, *sx_ca, *sy_ca;
587  int32_t sx = static_cast<int32_t>(0xffff * src->w / dst->w);
588  int32_t sy = static_cast<int32_t>(0xffff * src->h / dst->h);
589  int32_t sx_c = 0;
590  int32_t sy_c = 0;
591 
592  // Allocates memory and calculates row wide&height
593  int32_t* sx_a = new int32_t[dst->w + 1];
594  sx_ca = sx_a;
595  for (x = 0; x <= dst->w; x++) {
596  *sx_ca = sx_c;
597  sx_ca++;
598  sx_c &= 0xffff;
599  sx_c += sx;
600  }
601 
602  int32_t* sy_a = new int32_t[dst->h + 1];
603  sy_ca = sy_a;
604  for (y = 0; y <= dst->h; y++) {
605  *sy_ca = sy_c;
606  sy_ca++;
607  sy_c &= 0xffff;
608  sy_c += sy;
609  }
610  sy_ca = sy_a;
611 
612  // Transfers the image data
613 
614  if (SDL_MUSTLOCK(src)) {
615  SDL_LockSurface(src);
616  }
617 
618  if (SDL_MUSTLOCK(dst)) {
619  SDL_LockSurface(dst);
620  }
621 
622  for (y = 0; y < dst->h; y++) {
623  src_pointer = src_help_pointer;
624  sx_ca = sx_a;
625  for (x = 0; x < dst->w; x++) {
626  *dst_pointer = *src_pointer;
627  sx_ca++;
628  src_pointer += (*sx_ca >> 16);
629  dst_pointer++;
630  }
631  sy_ca++;
632  src_help_pointer = (uint32_t*)((uint8_t*)src_help_pointer + (*sy_ca >> 16) * src->pitch);
633  }
634 
635  if (SDL_MUSTLOCK(dst)) {
636  SDL_UnlockSurface(dst);
637  }
638  if (SDL_MUSTLOCK(src)) {
639  SDL_UnlockSurface(src);
640  }
641 
642  Image::saveAsPng(filename, *dst);
643 
644  // Free memory
645  SDL_FreeSurface(src);
646  SDL_FreeSurface(dst);
647  delete[] sx_a;
648  delete[] sy_a;
649  }
650  }
651 
652  void RenderBackendSDL::setClipArea(const Rect& cliparea, bool clear) {
653  SDL_Rect rect;
654  rect.x = cliparea.x;
655  rect.y = cliparea.y;
656  rect.w = cliparea.w;
657  rect.h = cliparea.h;
658  SDL_RenderSetClipRect(m_renderer, &rect);
659  if (clear) {
660  if (m_isbackgroundcolor) {
661  SDL_SetRenderDrawColor(m_renderer, m_backgroundcolor.r, m_backgroundcolor.g, m_backgroundcolor.b, 255);
662  } else {
663  SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, 255);
664  }
665  SDL_RenderFillRect(m_renderer, &rect);
666  }
667  }
668 
670  SDLImage* image = static_cast<SDLImage*>(img.get());
671  m_target = img->getSurface();
672  SDL_Texture* texture = image->getTexture();
673  if (!texture) {
674  texture = SDL_CreateTexture(m_renderer, m_rgba_format.format, SDL_TEXTUREACCESS_TARGET, m_target->w, m_target->h);
675  image->setTexture(texture);
676  }
677  SDL_SetRenderTarget(m_renderer, texture);
678  setClipArea(img->getArea(), discard);
679  }
680 
682  SDL_RenderPresent(m_renderer);
683  m_target = m_screen;
684  SDL_SetRenderTarget(m_renderer, NULL);
685  }
686 
687  void RenderBackendSDL::renderGuiGeometry(const std::vector<GuiVertex>& vertices, const std::vector<int>& indices, const DoublePoint& translation, ImagePtr texture) {
688 
689  }
690 }
uint8_t getDisplay() const
Returns the display index.
Definition: devicecaps.h:108
uint16_t getHeight() const
Returns the height of the screen mode.
Definition: devicecaps.h:68
static T ATan2(T _x, T _y)
Definition: fife_math.h:207
virtual void renderGuiGeometry(const std::vector< GuiVertex > &vertices, const std::vector< int > &indices, const DoublePoint &translation, ImagePtr texture)
Renders geometry required by gui.
Abstract interface for all the renderbackends.
uint32_t getSDLFlags() const
Returns the SDL flags used when testing this mode.
Definition: devicecaps.h:80
SDL_Surface * m_target
const uint32_t NULLMASK
Definition: fife_stdint.h:63
int8_t getRenderDriverIndex() const
Returns the index of the render driver.
Definition: devicecaps.h:124
uint32_t getHeight() const
virtual void createMainScreen(const ScreenMode &mode, const std::string &title, const std::string &icon)
Creates the mainscreen (the display window).
static T Cos(T _val)
Definition: fife_math.h:217
virtual const std::string & getName() const
The name of the renderbackend.
virtual void drawFillCircleSegment(const Point &p, uint32_t radius, int32_t sangle, int32_t eangle, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws a filled circle segment.
Base Class for Images.
Definition: image.h:48
virtual void renderVertexArrays()
Render the Vertex Arrays, only for primitives (points, lines,...)
static T Sqrt(T _val)
Definition: fife_math.h:277
T h
Height of the rectangle.
Definition: rect.h:93
Helper class to create log strings out from separate parts Usage: LMsg("some text") << variable << "...
Definition: logger.h:82
uint32_t next(octet_iterator &it, octet_iterator end)
Definition: checked.h:137
SDL_PixelFormat m_rgba_format
static T Floor(T _val)
Definition: fife_math.h:232
virtual void drawTriangle(const Point &p1, const Point &p2, const Point &p3, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws triangle between given points with given RGBA.
SDL_Window * m_window
virtual void resetStencilBuffer(uint8_t buffer)
Reset stencil buffer with given value.
T x
The X Coordinate.
Definition: rect.h:84
virtual void drawFillCircle(const Point &p, uint32_t radius, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws a filled circle.
The SDL implementation of the Image base class.
Definition: sdlimage.h:40
static void saveAsPng(const std::string &filename, const SDL_Surface &surface)
Saves the SDL_Surface to png format.
Definition: image.cpp:231
Rect getArea() const
Definition: image.cpp:176
void setTexture(SDL_Texture *texture)
Definition: sdlimage.cpp:228
virtual void captureScreen(const std::string &filename)
Creates a Screenshot and saves it to a file.
uint32_t getFormat() const
Returns the pixel format enum.
Definition: devicecaps.h:100
virtual void setClipArea(const Rect &cliparea, bool clear)
Sets given clip area into image.
const uint32_t RMASK
Definition: fife_stdint.h:53
static Logger _log(LM_AUDIO)
virtual void drawQuad(const Point &p1, const Point &p2, const Point &p3, const Point &p4, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws quad between given points with given RGBA.
SDL_Texture * getTexture()
Definition: sdlimage.cpp:224
virtual Image * createImage(IResourceLoader *loader=0)
virtual void disableScissorTest()
Disables scissor test on the render backend.
const uint32_t AMASK
Definition: fife_stdint.h:56
virtual void startFrame()
Called when a new frame starts.
virtual void setScreenMode(const ScreenMode &mode)
Sets the mainscreen display mode.
virtual bool putPixel(int32_t x, int32_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Writes pixel to given position.
unsigned char uint8_t
Definition: core.h:38
PointType2D< int32_t > Point
Definition: point.h:195
const uint32_t GMASK
Definition: fife_stdint.h:54
virtual void drawCircleSegment(const Point &p, uint32_t radius, int32_t sangle, int32_t eangle, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws a circle segment.
SDL_Surface * getSurface()
Definition: image.h:96
virtual void drawLightPrimitive(const Point &p, uint8_t intensity, float radius, int32_t subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue)
Draws a light primitive that based on a triangle fan.
virtual void startFrame()
Called when a new frame starts.
static T Sin(T _val)
Definition: fife_math.h:267
virtual void drawRectangle(const Point &p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws an axis parallel rectangle.
RenderBackendSDL(const SDL_Color &colorkey)
uint16_t getBPP() const
Returns the number of bits per pixel this mode uses.
Definition: devicecaps.h:72
virtual void drawBezier(const std::vector< Point > &points, int32_t steps, uint8_t width, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws bezier curve between given points with given RGBA and width.
virtual uint32_t getLightingModel() const
Gets the current light model.
virtual void detachRenderTarget()
Detaches current render surface.
virtual void resetLighting()
Reset lighting with default values.
virtual void changeRenderInfos(RenderDataType type, uint16_t elements, int32_t src, int32_t dst, bool light, bool stentest, uint8_t stenref, GLConstants stenop, GLConstants stenfunc, OverlayType otype=OVERLAY_TYPE_NONE)
Dirty helper function to change the render infos.
const uint32_t BMASK
Definition: fife_stdint.h:55
unsigned short uint16_t
Definition: core.h:39
T y
The Y Coordinate.
Definition: rect.h:87
SDL_Surface * m_screen
static num_type twoPi()
Definition: fife_math.h:135
SDL_Color m_backgroundcolor
virtual void fillRectangle(const Point &p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws a filled axis parallel rectangle.
#define FL_LOG(logger, msg)
Definition: logger.h:71
virtual void endFrame()
Called when a frame is finished and ready to be displayed.
virtual void clearBackBuffer()
Forces a clear of the backbuffer.
virtual void endFrame()
Called when a frame is finished and ready to be displayed.
TextureFiltering m_textureFilter
static num_type pi()
Definition: fife_math.h:134
virtual void changeBlending(int32_t scr, int32_t dst)
Change the Blendingmodel.
virtual void setLighting(float red, float green, float blue)
Set colors for lighting.
virtual void drawLine(const Point &p1, const Point &p2, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws line between given points with given RGBA.
Point getBezierPoint(const std::vector< Point > &points, int32_t elements, float t)
Helper that returns an interpolated Point.
virtual void drawPolyLine(const std::vector< Point > &points, uint8_t width, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws lines between given points with given RGBA and width.
uint32_t getWidth() const
T * get() const
allows direct access to underlying pointer
Definition: sharedptr.h:155
virtual void attachRenderTarget(ImagePtr &img, bool discard)
Attaches given image as a new render surface.
virtual void drawCircle(const Point &p, uint32_t radius, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws a circle.
ScreenMode m_screenMode
RenderDataType
void deinit()
Performs cleanup actions.
unsigned int uint32_t
Definition: core.h:40
uint16_t getWidth() const
Returns the width of the screen mode.
Definition: devicecaps.h:62
uint16_t getRefreshRate() const
Returns the refresh rate in Hz of this mode.
Definition: devicecaps.h:76
virtual void drawThickLine(const Point &p1, const Point &p2, uint8_t width, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws line between given points with given RGBA and width.
virtual void addImageToArray(uint32_t id, const Rect &rec, float const *st, uint8_t alpha, uint8_t const *rgba)
Add the Image data to the array.
T w
Width of the rectangle.
Definition: rect.h:90
virtual void enableScissorTest()
Enables scissor test on the render backend.
virtual void setLightingModel(uint32_t lighting)
Initializes the light.
virtual void drawVertex(const Point &p, const uint8_t size, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Draws a quad that represents a vertex with given RGBA.
virtual void init(const std::string &driver)
Initializes the backend.
bool isFullScreen() const
True if this is a fullscreen mode.
Definition: devicecaps.h:84