FIFE
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
renderbackendopengl.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2013 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 // Platform specific includes
25 
26 // 3rd party library includes
27 #include <SDL.h>
28 
29 // FIFE includes
30 #include "util/base/exception.h"
31 #include "util/log/logger.h"
32 #include "video/devicecaps.h"
33 
34 #include "glimage.h"
35 #include "renderbackendopengl.h"
36 #include "SDL_image.h"
37 
38 
39 namespace FIFE {
43  static Logger _log(LM_VIDEO);
44 
46  public:
47  RenderObject(GLenum m, uint16_t s, uint32_t t=0):
48  mode(m),
49  size(s),
50  texture_id(t),
51  src(4),
52  dst(5),
53  light(true),
54  stencil_test(false),
55  stencil_ref(0),
56  stencil_op(0),
57  stencil_func(0),
58  multitextured(false) {}
59 
60  GLenum mode;
63  int32_t src;
64  int32_t dst;
65  bool light;
68  GLenum stencil_op;
69  GLenum stencil_func;
72  };
73 
74  RenderBackendOpenGL::RenderBackendOpenGL(const SDL_Color& colorkey)
75  : RenderBackend(colorkey), m_mask_overlays(0){
76 
77  m_state.tex_enabled[0] = false;
78  m_state.tex_enabled[1] = false;
79  m_state.texture[0] = 0;
80  m_state.texture[1] = 0;
81  m_state.active_tex = 0;
82 
84  m_state.tex_pointer[0] = 0;
85  m_state.tex_pointer[1] = 0;
87 
88  m_state.sten_enabled = false;
89  m_state.sten_ref = 0;
90  m_state.sten_buf = 0;
91  m_state.sten_op = 0;
92  m_state.sten_func = 0;
93 
94  m_state.lightmodel = 0;
95  m_state.light_enabled = false;
96 
97  m_state.env_color[0] = 0;
98  m_state.env_color[1] = 0;
99  m_state.env_color[2] = 0;
100  m_state.env_color[3] = 0;
101  m_state.blend_src = GL_SRC_ALPHA;
102  m_state.blend_dst = GL_ONE_MINUS_SRC_ALPHA;
103  m_state.alpha_enabled = false;
104  m_state.scissor_test = true;
105  }
106 
108  glDeleteTextures(1, &m_mask_overlays);
109  if(GLEE_EXT_framebuffer_object && m_useframebuffer) {
110  glDeleteFramebuffers(1, &m_fbo_id);
111  }
112  deinit();
113  }
114 
115  const std::string& RenderBackendOpenGL::getName() const {
116  static std::string backend_name = "OpenGL";
117  return backend_name;
118  }
119 
120  void RenderBackendOpenGL::init(const std::string& driver) {
121  // note: driver has no affect on the opengl renderer so do nothing with it here.
122  Uint32 flags = SDL_INIT_VIDEO;
123  if (SDL_InitSubSystem(flags) < 0)
124  throw SDLException(SDL_GetError());
125  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
126  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
127 
128  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // temporary hack
129  }
130 
133  glClear(GL_COLOR_BUFFER_BIT);
135  }
136 
137  void RenderBackendOpenGL::createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon){
138  if(icon != "") {
139  SDL_Surface *img = IMG_Load(icon.c_str());
140  if(img != NULL) {
141  SDL_WM_SetIcon(img, 0);
142  SDL_FreeSurface(img);
143  }
144  }
145 
146  SDL_WM_SetCaption(title.c_str(), 0);
147  setScreenMode(mode);
148  }
149 
151  uint16_t width = mode.getWidth();
152  uint16_t height = mode.getHeight();
153  uint16_t bitsPerPixel = mode.getBPP();
154  uint32_t flags = mode.getSDLFlags();
155 
156  if (bitsPerPixel != 0) {
157  uint16_t bpp = SDL_VideoModeOK(width, height, bitsPerPixel, flags);
158  if (!bpp){
159  throw SDLException("Selected video mode not supported!");
160  }
161  }
162 
163  if(m_screen) {
164  SDL_FreeSurface(m_screen);
165  }
166  m_screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags);
167  if( !m_screen ) {
168  throw SDLException("Unable to set video mode selected!");
169  }
170  m_target = m_screen;
171 
172  FL_LOG(_log, LMsg("RenderBackendOpenGL")
173  << "Videomode " << width << "x" << height
174  << " at " << int32_t(bitsPerPixel) << " bpp");
175 
176  m_rgba_format = *(m_screen->format);
177  m_rgba_format.Rmask = RMASK;
178  m_rgba_format.Gmask = GMASK;
179  m_rgba_format.Bmask = BMASK;
180  m_rgba_format.Amask = AMASK;
181 
182  //update the screen mode with the actual flags used
183  m_screenMode = ScreenMode(width,
184  height,
185  bitsPerPixel,
186  m_screen->flags);
187 
188  if (!m_screen) {
189  throw SDLException(SDL_GetError());
190  }
191 
192  glViewport(0, 0, width, height);
193  glMatrixMode(GL_PROJECTION);
194  glLoadIdentity();
195  glOrtho(0, width, height, 0, -1, 1);
196  glMatrixMode(GL_MODELVIEW);
197  glLoadIdentity();
198 
199  glEnable(GL_CULL_FACE);
200  glFrontFace(GL_CCW);
201  glCullFace(GL_BACK);
202 
203  glPixelStorei(GL_PACK_ALIGNMENT, 1);
204  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
205 
206  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
207 
208  glEnable(GL_BLEND);
209  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
210 
211  glEnable(GL_SCISSOR_TEST);
212 
213  glEnableClientState(GL_COLOR_ARRAY);
214  glEnableClientState(GL_VERTEX_ARRAY);
215 
217 
218  glPointSize(1.0);
219  glLineWidth(1.0);
220 
221  if(GLEE_EXT_framebuffer_object && m_useframebuffer) {
222  glGenFramebuffers(1, &m_fbo_id);
223  }
224  }
225 
228  }
229 
231  SDL_GL_SwapBuffers();
233  }
234 
236  return new GLImage(loader);
237  }
238 
239  Image* RenderBackendOpenGL::createImage(const std::string& name, IResourceLoader* loader) {
240  return new GLImage(name, loader);
241  }
242 
243  Image* RenderBackendOpenGL::createImage(SDL_Surface* surface) {
244  // Given an abritary surface, we must convert it to the format GLImage will understand.
245  // It's easiest to let SDL do this for us.
246 
247  // Uh. Gotta love this :-)
248  // Check for colorkey too?
249  // Leave out the loss/shift checks?
250  if (32 == surface->format->BitsPerPixel
251  && m_rgba_format.Rmask == surface->format->Rmask
252  && m_rgba_format.Gmask == surface->format->Gmask
253  && m_rgba_format.Bmask == surface->format->Bmask
254  && m_rgba_format.Amask == surface->format->Amask
255  && m_rgba_format.Rshift == surface->format->Rshift
256  && m_rgba_format.Gshift == surface->format->Gshift
257  && m_rgba_format.Bshift == surface->format->Bshift
258  && m_rgba_format.Ashift == surface->format->Ashift
259  && m_rgba_format.Rloss == surface->format->Rloss
260  && m_rgba_format.Gloss == surface->format->Gloss
261  && m_rgba_format.Bloss == surface->format->Bloss
262  && m_rgba_format.Aloss == surface->format->Aloss
263  && surface->flags & SDL_SRCALPHA ) {
264 
265  return new GLImage(surface);
266  }
267 
268  uint8_t bpp = m_rgba_format.BitsPerPixel;
269  m_rgba_format.BitsPerPixel = 32;
270  SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA);
271  m_rgba_format.BitsPerPixel = bpp;
272  GLImage* image = new GLImage(conv);
273 
274  SDL_FreeSurface(surface);
275  return image;
276  }
277 
278  Image* RenderBackendOpenGL::createImage(const std::string& name, SDL_Surface* surface) {
279  // Given an abritary surface, we must convert it to the format GLImage will understand.
280  // It's easiest to let SDL do this for us.
281 
282  // Uh. Gotta love this :-)
283  // Check for colorkey too?
284  // Leave out the loss/shift checks?
285  if (32 == surface->format->BitsPerPixel
286  && m_rgba_format.Rmask == surface->format->Rmask
287  && m_rgba_format.Gmask == surface->format->Gmask
288  && m_rgba_format.Bmask == surface->format->Bmask
289  && m_rgba_format.Amask == surface->format->Amask
290  && m_rgba_format.Rshift == surface->format->Rshift
291  && m_rgba_format.Gshift == surface->format->Gshift
292  && m_rgba_format.Bshift == surface->format->Bshift
293  && m_rgba_format.Ashift == surface->format->Ashift
294  && m_rgba_format.Rloss == surface->format->Rloss
295  && m_rgba_format.Gloss == surface->format->Gloss
296  && m_rgba_format.Bloss == surface->format->Bloss
297  && m_rgba_format.Aloss == surface->format->Aloss
298  && surface->flags & SDL_SRCALPHA ) {
299 
300  return new GLImage(name, surface);
301  }
302 
303  uint8_t bpp = m_rgba_format.BitsPerPixel;
304  m_rgba_format.BitsPerPixel = 32;
305  SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA);
306  m_rgba_format.BitsPerPixel = bpp;
307  GLImage* image = new GLImage(name, conv);
308 
309  SDL_FreeSurface(surface);
310  return image;
311  }
312 
314  return new GLImage(data, width, height);
315  }
316 
317  Image* RenderBackendOpenGL::createImage(const std::string& name, const uint8_t* data, uint32_t width, uint32_t height) {
318  return new GLImage(name, data, width, height);
319  }
320 
322  if (m_state.lightmodel != lighting) {
323  if (m_state.lightmodel != 0) {
324  disableLighting();
325  glDisable(GL_COLOR_MATERIAL);
326  } else if (lighting != 0) {
327  enableLighting();
328  glEnable(GL_LIGHT0);
329  glColorMaterial(GL_FRONT, GL_DIFFUSE);
330  glEnable(GL_COLOR_MATERIAL);
331  }
332  m_state.lightmodel = lighting;
333  }
334  }
335 
337  return m_state.lightmodel;
338  }
339 
341  if(m_state.tex_enabled[texUnit] == false) {
342  if(m_state.active_tex != texUnit) {
343  m_state.active_tex = texUnit;
344  glActiveTexture(GL_TEXTURE0 + texUnit);
345  }
346  m_state.tex_enabled[texUnit] = true;
347 
348  glEnable(GL_TEXTURE_2D);
349  if(texUnit == 0) {
350  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
351  }
352  }
353  }
354 
356  {
357  if(m_state.tex_enabled[texUnit] == true) {
358  if(m_state.active_tex != texUnit) {
359  m_state.active_tex = texUnit;
360  glActiveTexture(GL_TEXTURE0 + texUnit);
361  }
362  m_state.tex_enabled[texUnit] = false;
363 
364  glDisable(GL_TEXTURE_2D);
365  if(texUnit == 0) {
366  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
367  }
368  }
369  }
370 
371  void RenderBackendOpenGL::bindTexture(uint32_t texUnit, GLuint texId) {
372  enableTextures(texUnit);
373 
374  if(m_state.texture[texUnit] != texId) {
375  if(m_state.active_tex != texUnit) {
376  m_state.active_tex = texUnit;
377  glActiveTexture(GL_TEXTURE0 + texUnit);
378  }
379  m_state.texture[texUnit] = texId;
380  glBindTexture(GL_TEXTURE_2D, texId);
381  }
382  }
383 
384  void RenderBackendOpenGL::bindTexture(GLuint texId) {
385  if(m_state.texture[m_state.active_tex] != texId) {
387  glBindTexture(GL_TEXTURE_2D, texId);
388  }
389  }
390 
392  if (m_state.lightmodel != 0 && !m_state.light_enabled) {
393  glEnable(GL_LIGHTING);
394  m_state.light_enabled = true;
395  }
396  }
397 
399  if (m_state.lightmodel != 0 && m_state.light_enabled) {
400  glDisable(GL_LIGHTING);
401  m_state.light_enabled = false;
402  }
403  }
404 
405  void RenderBackendOpenGL::setLighting(float red, float green, float blue) {
406  if (m_state.lightmodel != 0) {
407  GLfloat lightDiffuse[] = {red, green, blue, 1.0f};
408  glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
409  }
410  }
411 
413  if (m_state.lightmodel != 0) {
414  setLighting(1.0, 1.0, 1.0);
415  }
416  }
417 
419  if (!m_state.sten_enabled) {
420  glEnable(GL_STENCIL_TEST);
421  m_state.sten_enabled = true;
422  }
423  }
424 
426  if (m_state.sten_enabled) {
427  glDisable(GL_STENCIL_TEST);
428  m_state.sten_enabled = false;
429  }
430  }
431 
432  void RenderBackendOpenGL::setStencilTest(uint8_t stencil_ref, GLenum stencil_op, GLenum stencil_func) {
434  if(m_state.sten_op != stencil_op) {
435  m_state.sten_op = stencil_op;
436  glStencilOp(GL_KEEP, GL_KEEP, m_state.sten_op);
437  }
438 
439  if(m_state.sten_ref != stencil_ref || m_state.sten_func != stencil_func) {
440  m_state.sten_ref = stencil_ref;
441  m_state.sten_func = stencil_func;
442  glStencilFunc(m_state.sten_func, stencil_ref, 0xff);
443  }
444  }
445 
447  if (buffer != m_state.sten_buf) {
448  m_state.sten_buf = buffer;
449  glClearStencil(buffer);
450  }
452  glClear(GL_STENCIL_BUFFER_BIT);
454  }
455 
457  return m_state.sten_ref;
458  }
459 
461  if (!m_state.alpha_enabled) {
462  glEnable(GL_ALPHA_TEST);
463  m_state.alpha_enabled = true;
464  }
465  }
466 
468  if (m_state.alpha_enabled) {
469  glDisable(GL_ALPHA_TEST);
470  m_state.alpha_enabled = false;
471  }
472  }
473 
474  void RenderBackendOpenGL::setAlphaTest(float ref_alpha) {
475  enableAlphaTest();
476  glAlphaFunc(GL_GREATER, ref_alpha);
477  }
478 
480  if (memcmp(m_state.env_color, rgba, sizeof(uint8_t) * 4)) {
481 
482  memcpy(m_state.env_color, rgba, sizeof(uint8_t) * 4);
483  GLfloat rgbaf[4] = {
484  static_cast<float>(m_state.env_color[0]) / 255.0f,
485  static_cast<float>(m_state.env_color[1]) / 255.0f,
486  static_cast<float>(m_state.env_color[2]) / 255.0f,
487  static_cast<float>(m_state.env_color[3]) / 255.0f};
488 
489  if(m_state.active_tex != 1) {
490  m_state.active_tex = 1;
491  glActiveTexture(GL_TEXTURE1);
492  }
493 
494  glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgbaf);
495  }
496  }
497 
498  void RenderBackendOpenGL::setVertexPointer(GLsizei stride, const GLvoid* ptr) {
499  if(m_state.vertex_pointer != ptr) {
500  m_state.vertex_pointer = ptr;
501  glVertexPointer(2, GL_FLOAT, stride, ptr);
502  }
503  }
504 
505  void RenderBackendOpenGL::setColorPointer(GLsizei stride, const GLvoid* ptr) {
506  if(m_state.color_pointer != ptr) {
507  m_state.color_pointer = ptr;
508  glColorPointer(4, GL_UNSIGNED_BYTE, stride, ptr);
509  }
510  }
511 
512  void RenderBackendOpenGL::setTexCoordPointer(uint32_t texUnit, GLsizei stride, const GLvoid* ptr) {
513  if(m_state.tex_pointer[texUnit] != ptr) {
514  if(m_state.active_client_tex != texUnit) {
515  m_state.active_client_tex = texUnit;
516  glClientActiveTexture(GL_TEXTURE0 + texUnit);
517  }
518  m_state.tex_pointer[texUnit] = ptr;
519  glTexCoordPointer(2, GL_FLOAT, stride, ptr);
520  }
521  }
522 
524  if(m_state.scissor_test == false) {
525  m_state.scissor_test = true;
526  glEnable(GL_SCISSOR_TEST);
527  }
528  }
529 
531  if(m_state.scissor_test == true) {
532  m_state.scissor_test = false;
533  glDisable(GL_SCISSOR_TEST);
534  }
535  }
536 
537  void RenderBackendOpenGL::changeBlending(int32_t src, int32_t dst) {
538  GLenum src_fact;
539  GLenum dst_fact;
540 
541  switch(src) {
542  case 0 : src_fact = GL_ZERO; break;
543  case 1 : src_fact = GL_ONE; break;
544  case 2 : src_fact = GL_DST_COLOR; break;
545  case 3 : src_fact = GL_ONE_MINUS_DST_COLOR; break;
546  case 4 : src_fact = GL_SRC_ALPHA; break;
547  case 5 : src_fact = GL_ONE_MINUS_SRC_ALPHA; break;
548  case 6 : src_fact = GL_DST_ALPHA; break;
549  case 7 : src_fact = GL_ONE_MINUS_DST_ALPHA; break;
550 
551  default : src_fact = GL_DST_COLOR; break;
552  }
553 
554  switch(dst) {
555  case 0 : dst_fact = GL_ZERO; break;
556  case 1 : dst_fact = GL_ONE; break;
557  case 2 : dst_fact = GL_SRC_COLOR; break;
558  case 3 : dst_fact = GL_ONE_MINUS_SRC_COLOR; break;
559  case 4 : dst_fact = GL_SRC_ALPHA; break;
560  case 5 : dst_fact = GL_ONE_MINUS_SRC_ALPHA; break;
561  case 6 : dst_fact = GL_DST_ALPHA; break;
562  case 7 : dst_fact = GL_ONE_MINUS_DST_ALPHA; break;
563 
564  default : dst_fact = GL_SRC_ALPHA; break;
565  }
566 
567  if (m_state.blend_src != src_fact || m_state.blend_dst != dst_fact) {
568  m_state.blend_src = src_fact;
569  m_state.blend_dst = dst_fact;
570  glBlendFunc(src_fact, dst_fact);
571  }
572  }
573 
574  void RenderBackendOpenGL::changeRenderInfos(uint16_t elements, int32_t src, int32_t dst, bool light,
575  bool stentest, uint8_t stenref, GLConstants stenop, GLConstants stenfunc) {
576 
577  uint16_t count = 0;
578  uint32_t size = m_render_objects.size();
579  while (count != elements) {
580  ++count;
581  RenderObject& r = m_render_objects.at(size-count);
582 
583  r.src = src;
584  r.dst = dst;
585  r.light = light;
586  if (stentest) {
587  r.stencil_test = stentest;
588  r.stencil_ref = stenref;
589  r.stencil_op = stenop;
590  r.stencil_func = stenfunc;
591  }
592  }
593  }
594 
596  if (!m_render_objects.empty()) {
597  //bools to indicate changes
598  bool type = false;
599  bool texture = false;
600  bool blending = false;
601  bool light = false;
602  bool stencil = false;
603  bool render = false;
604  bool mt = false;
605 
606  //stride
607  const uint32_t stride = sizeof(renderData);
608  const uint32_t stride2T = sizeof(renderData2T);
609 
610  if(!m_render_objects[0].multitextured) {
611  //set pointer
612  setVertexPointer(stride, &m_render_datas[0].vertex);
613  setTexCoordPointer(0, stride, &m_render_datas[0].texel);
614  setColorPointer(stride, &m_render_datas[0].color);
615  }
616 
617  // array index
618  int32_t index = 0;
619  // elements to render
620  uint32_t elements = 0;
621  // render mode
622  GLenum mode = GL_QUADS;
623  // texture id
624  uint32_t texture_id = 0;
625  // src blending mode
626  int32_t src = 4;
627  // dst blending mode
628  int32_t dst = 5;
629 
630  bool multitextured = false;
631  uint8_t color[4] = {0};
632 
633  int32_t index2T = 0;
634  uint32_t elements2T = 0;
635 
636  int32_t* currentIndex = &index;
637  uint32_t* currentElements = &elements;
638 
639  for(std::vector<RenderObject>::iterator ir = m_render_objects.begin(); ir != m_render_objects.end(); ++ir) {
640  RenderObject& ro = (*ir);
641 
642  //first we look for changes
643  if (ro.mode != mode) {
644  type = true;
645  render = true;
646  }
647  if (ro.texture_id != texture_id) {
648  texture = true;
649  render = true;
650  }
651  if (m_state.lightmodel != 0) {
652  if (ro.src != src || ro.dst != dst) {
653  blending = true;
654  render = true;
655  }
656  if (ro.light != m_state.light_enabled) {
657  light = true;
658  render = true;
659  }
660  if (ro.stencil_test != m_state.sten_enabled) {
661  stencil = true;
662  render = true;
663  } else if (ro.stencil_test) {
664  if (ro.stencil_ref != m_state.sten_ref ||
665  ro.stencil_op != m_state.sten_op ||
667  stencil = true;
668  render = true;
669  }
670  }
671  }
672  if (ro.multitextured != multitextured ||
673  (ro.multitextured == true && memcmp(color, ro.rgba, sizeof(uint8_t) * 4))) {
674  mt = true;
675  render = true;
676  }
677 
678  // if changes then we render all previously elements
679  if (render) {
680  if (*currentElements > 0) {
681  //render
682  glDrawArrays(mode, *currentIndex, *currentElements);
683  *currentIndex += *currentElements;
684  }
685  // switch mode
686  if (type) {
687  mode = ro.mode;
688  type = false;
689  }
690 
691  if(mt) {
692  if(ro.multitextured) {
693  enableTextures(1); // or bindTexture(1, maskForOverlays); if we change it somewhere
695  enableTextures(0);
696 
697  // set pointers
698  setVertexPointer(stride2T, &m_render_datas2T[0].vertex);
699  setColorPointer(stride2T, &m_render_datas2T[0].color);
700  setTexCoordPointer(1, stride2T, &m_render_datas2T[0].texel2);
701  setTexCoordPointer(0, stride2T, &m_render_datas2T[0].texel);
702 
703  memcpy(color, ro.rgba, sizeof(uint8_t) * 4);
704  multitextured = true;
705  currentElements = &elements2T;
706  currentIndex = &index2T;
707 
708  } else {
709  disableTextures(1);
710  enableTextures(0);
711 
712  // set pointers
713  setVertexPointer(stride, &m_render_datas[0].vertex);
714  setTexCoordPointer(0, stride, &m_render_datas[0].texel);
715  setColorPointer(stride, &m_render_datas[0].color);
716 
717  multitextured = false;
718  currentIndex = &index;
719  currentElements = &elements;
720  }
721  mt = false;
722  }
723 
724  // switch texturing
725  if (texture) {
726  if (ro.texture_id != 0) {
727  bindTexture(0, ro.texture_id);
728  texture_id = ro.texture_id;
729  } else {
730  disableTextures(0);
731  texture_id = 0;
732  }
733  texture = false;
734  }
735 
736  // set element to current size
737  *currentElements = ro.size;
738 
739  // if lighting is enabled we have to consider a few more values
740  if (m_state.lightmodel != 0) {
741  // change blending
742  if (blending) {
743  src = ro.src;
744  dst = ro.dst;
745  changeBlending(ro.src, ro.dst);
746  blending = false;
747  }
748  // change light
749  if (light) {
750  if (ro.light && !m_state.light_enabled) {
751  enableLighting();
752  } else if (!ro.light && m_state.light_enabled) {
753  disableLighting();
754  }
755  light = false;
756  }
757  // change stencil
758  if (stencil) {
759  if (ro.stencil_test) {
761  setAlphaTest(0.0);
762  } else {
765  }
766  stencil = false;
767  }
768  }
769  render = false;
770  } else {
771  // else add the element
772  *currentElements += ro.size;
773  }
774  }
775  // render
776  glDrawArrays(mode, *currentIndex, *currentElements);
777 
778  //reset all states
779  disableTextures(1);
780  disableTextures(0);
781 
782  if (m_state.lightmodel != 0) {
783  changeBlending(4, 5);
784  disableLighting();
787  }
788 
789  m_render_objects.clear();
790  m_render_datas.clear();
791  m_render_datas2T.clear();
792  }
793  }
794 
795  bool RenderBackendOpenGL::putPixel(int32_t x, int32_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
796  if ((x < 0) || (x >= (int32_t)m_target->w) ||
797  (y < 0) || (y >= (int32_t)m_target->h)) {
798  return false;
799  }
800  renderData rd;
801  rd.vertex[0] = static_cast<float>(x);
802  rd.vertex[1] = static_cast<float>(y);
803  rd.color[0] = r;
804  rd.color[1] = g;
805  rd.color[2] = b;
806  rd.color[3] = a;
807  m_render_datas.push_back(rd);
808 
809  RenderObject ro(GL_POINTS, 1);
810  m_render_objects.push_back(ro);
811 
812  return true;
813  }
814 
815  void RenderBackendOpenGL::drawLine(const Point& p1, const Point& p2, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
816  renderData rd;
817  rd.vertex[0] = static_cast<float>(p1.x);
818  rd.vertex[1] = static_cast<float>(p1.y);
819  rd.color[0] = r;
820  rd.color[1] = g;
821  rd.color[2] = b;
822  rd.color[3] = a;
823  m_render_datas.push_back(rd);
824 
825  rd.vertex[0] = static_cast<float>(p2.x);
826  rd.vertex[1] = static_cast<float>(p2.y);
827  m_render_datas.push_back(rd);
828 
829  RenderObject ro(GL_LINES, 2);
830  m_render_objects.push_back(ro);
831  }
832 
833  void RenderBackendOpenGL::drawTriangle(const Point& p1, const Point& p2, const Point& p3, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
834  renderData rd;
835  rd.vertex[0] = static_cast<float>(p1.x);
836  rd.vertex[1] = static_cast<float>(p1.y);
837  rd.color[0] = r;
838  rd.color[1] = g;
839  rd.color[2] = b;
840  rd.color[3] = a;
841  m_render_datas.push_back(rd);
842 
843  rd.vertex[0] = static_cast<float>(p2.x);
844  rd.vertex[1] = static_cast<float>(p2.y);
845  m_render_datas.push_back(rd);
846 
847  rd.vertex[0] = static_cast<float>(p3.x);
848  rd.vertex[1] = static_cast<float>(p3.y);
849  m_render_datas.push_back(rd);
850 
851  RenderObject ro(GL_TRIANGLES, 3);
852  m_render_objects.push_back(ro);
853  }
854 
856  renderData rd;
857  rd.vertex[0] = static_cast<float>(p.x);
858  rd.vertex[1] = static_cast<float>(p.y);
859  rd.color[0] = r;
860  rd.color[1] = g;
861  rd.color[2] = b;
862  rd.color[3] = a;
863  m_render_datas.push_back(rd);
864  rd.vertex[0] = static_cast<float>(p.x+w);
865 
866  m_render_datas.push_back(rd);
867  rd.vertex[1] = static_cast<float>(p.y+h);
868 
869  m_render_datas.push_back(rd);
870  rd.vertex[0] = static_cast<float>(p.x);
871  m_render_datas.push_back(rd);
872 
873  RenderObject ro(GL_LINE_LOOP, 4);
874  m_render_objects.push_back(ro);
875  }
876 
878  renderData rd;
879  rd.vertex[0] = static_cast<float>(p.x);
880  rd.vertex[1] = static_cast<float>(p.y);
881  rd.color[0] = r;
882  rd.color[1] = g;
883  rd.color[2] = b;
884  rd.color[3] = a;
885  m_render_datas.push_back(rd);
886 
887  rd.vertex[1] = static_cast<float>(p.y+h);
888  m_render_datas.push_back(rd);
889 
890  rd.vertex[0] = static_cast<float>(p.x+w);
891  m_render_datas.push_back(rd);
892 
893  rd.vertex[1] = static_cast<float>(p.y);
894  m_render_datas.push_back(rd);
895 
896  RenderObject ro(GL_QUADS, 4);
897  m_render_objects.push_back(ro);
898  }
899 
900  void RenderBackendOpenGL::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) {
901  renderData rd;
902  rd.vertex[0] = static_cast<float>(p1.x);
903  rd.vertex[1] = static_cast<float>(p1.y);
904  rd.color[0] = r;
905  rd.color[1] = g;
906  rd.color[2] = b;
907  rd.color[3] = a;
908  m_render_datas.push_back(rd);
909 
910  rd.vertex[0] = static_cast<float>(p2.x);
911  rd.vertex[1] = static_cast<float>(p2.y);
912  m_render_datas.push_back(rd);
913 
914  rd.vertex[0] = static_cast<float>(p3.x);
915  rd.vertex[1] = static_cast<float>(p3.y);
916  m_render_datas.push_back(rd);
917 
918  rd.vertex[0] = static_cast<float>(p4.x);
919  rd.vertex[1] = static_cast<float>(p4.y);
920  m_render_datas.push_back(rd);
921 
922  RenderObject ro(GL_QUADS, 4);
923  m_render_objects.push_back(ro);
924  }
925 
926  void RenderBackendOpenGL::drawVertex(const Point& p, const uint8_t size, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
927  renderData rd;
928  rd.vertex[0] = static_cast<float>(p.x-size);
929  rd.vertex[1] = static_cast<float>(p.y+size);
930  rd.color[0] = r;
931  rd.color[1] = g;
932  rd.color[2] = b;
933  rd.color[3] = a;
934  m_render_datas.push_back(rd);
935 
936  rd.vertex[0] = static_cast<float>(p.x+size);
937  m_render_datas.push_back(rd);
938 
939  rd.vertex[1] = static_cast<float>(p.y-size);
940  m_render_datas.push_back(rd);
941 
942  rd.vertex[0] = static_cast<float>(p.x-size);
943  m_render_datas.push_back(rd);
944 
945  RenderObject ro(GL_LINE_LOOP, 4);
946  m_render_objects.push_back(ro);
947  }
948 
949  void RenderBackendOpenGL::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) {
950  const float step = Mathf::twoPi()/subdivisions;
951  renderData rd;;
952  for(float angle=0; angle<=Mathf::twoPi(); angle+=step){
953  rd.vertex[0] = static_cast<float>(p.x);
954  rd.vertex[1] = static_cast<float>(p.y);
955  rd.color[0] = red;
956  rd.color[1] = green;
957  rd.color[2] = blue;
958  rd.color[3] = intensity;
959  m_render_datas.push_back(rd);
960 
961  rd.vertex[0] = radius*Mathf::Cos(angle+step)*xstretch + p.x;
962  rd.vertex[1] = radius*Mathf::Sin(angle+step)*ystretch + p.y;
963  rd.color[0] = 0;
964  rd.color[1] = 0;
965  rd.color[2] = 0;
966  rd.color[3] = 255;
967  m_render_datas.push_back(rd);
968 
969  rd.vertex[0] = radius*Mathf::Cos(angle)*xstretch + p.x;
970  rd.vertex[1] = radius*Mathf::Sin(angle)*ystretch + p.y;
971  m_render_datas.push_back(rd);
972 
973  RenderObject ro(GL_TRIANGLES, 3);
974  m_render_objects.push_back(ro);
975  }
976  }
977 
978  void RenderBackendOpenGL::addImageToArray(uint32_t id, const Rect& rect, float const* st, uint8_t alpha, uint8_t const* rgba) {
979  if (!rgba) {
980  renderData rd;
981  rd.vertex[0] = static_cast<float>(rect.x);
982  rd.vertex[1] = static_cast<float>(rect.y);
983  rd.texel[0] = st[0];
984  rd.texel[1] = st[1];
985  rd.color[0] = 255;
986  rd.color[1] = 255;
987  rd.color[2] = 255;
988  rd.color[3] = alpha;
989  m_render_datas.push_back(rd);
990 
991  rd.vertex[0] = static_cast<float>(rect.x);
992  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
993  rd.texel[1] = st[3];
994  m_render_datas.push_back(rd);
995 
996  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
997  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
998  rd.texel[0] = st[2];
999  m_render_datas.push_back(rd);
1000 
1001  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1002  rd.vertex[1] = static_cast<float>(rect.y);
1003  rd.texel[1] = st[1];
1004  m_render_datas.push_back(rd);
1005 
1006  RenderObject ro(GL_QUADS, 4, id);
1007  m_render_objects.push_back(ro);
1008  } else {
1009  renderData2T rd;
1010  rd.vertex[0] = static_cast<float>(rect.x);
1011  rd.vertex[1] = static_cast<float>(rect.y);
1012  rd.texel[0] = st[0];
1013  rd.texel[1] = st[1];
1014  rd.texel2[0] = 0.0;
1015  rd.texel2[1] = 0.0;
1016  rd.color[0] = 255;
1017  rd.color[1] = 255;
1018  rd.color[2] = 255;
1019  rd.color[3] = alpha;
1020  m_render_datas2T.push_back(rd);
1021 
1022  rd.vertex[0] = static_cast<float>(rect.x);
1023  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1024  rd.texel[1] = st[3];
1025  rd.texel2[1] = 1.0;
1026  m_render_datas2T.push_back(rd);
1027 
1028  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1029  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1030  rd.texel[0] = st[2];
1031  rd.texel2[0] = 1.0;
1032  m_render_datas2T.push_back(rd);
1033 
1034  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1035  rd.vertex[1] = static_cast<float>(rect.y);
1036  rd.texel[1] = st[1];
1037  rd.texel2[1] = 0.0;
1038  m_render_datas2T.push_back(rd);
1039 
1040  RenderObject ro(GL_QUADS, 4, id);
1041  ro.multitextured = true;
1042  ro.rgba[0] = rgba[0];
1043  ro.rgba[1] = rgba[1];
1044  ro.rgba[2] = rgba[2];
1045  ro.rgba[3] = rgba[3];
1046  m_render_objects.push_back(ro);
1047  }
1048  }
1049 
1051  glActiveTexture(GL_TEXTURE1);
1052  glEnable(GL_TEXTURE_2D);
1053 
1054  if(m_mask_overlays == 0) {
1055  // Constant texture - can be constant across every tilesets
1056  glGenTextures(1, &m_mask_overlays);
1057 
1058  uint8_t dummydata[3] = {127, 127, 127};
1059  glBindTexture(GL_TEXTURE_2D, m_mask_overlays);
1060  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1061  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1062  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1063  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1064  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0,
1065  GL_RGB, GL_UNSIGNED_BYTE, dummydata);
1066  } else {
1067  glBindTexture(GL_TEXTURE_2D, m_mask_overlays);
1068  }
1069 
1071 
1072  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1073  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
1074  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
1075 
1076  // Arg0
1077  glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
1078  glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
1079  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1080  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1081 
1082  // The alpha component is taken only from 0th tex unit which is
1083  // Arg0 in our case, therefore we doesn't need to set operands
1084  // and sources for the rest of arguments
1085 
1086  // Arg1
1087  glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
1088  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
1089 
1090  // Arg2
1091  // uses alpha part of environmental color as interpolation factor
1092  glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
1093  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
1094 
1095  // Return to normal sampling mode
1096  glActiveTexture(GL_TEXTURE1);
1097  glDisable(GL_TEXTURE_2D);
1098  glActiveTexture(GL_TEXTURE0);
1099 
1100  // For now it's unneecessary - Only needed if we intend to use the 2nd texture unit in different case
1101  //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1102  }
1103 
1104  void RenderBackendOpenGL::captureScreen(const std::string& filename) {
1105  const uint32_t swidth = getWidth();
1106  const uint32_t sheight = getHeight();
1107 
1108  uint8_t *pixels;
1109  SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, sheight, 24,
1110  RMASK, GMASK, BMASK, NULLMASK);
1111 
1112  if (!surface) {
1113  return;
1114  }
1115 
1116  SDL_LockSurface(surface);
1117  pixels = new uint8_t[swidth * sheight * 3];
1118  glReadPixels(0, 0, swidth, sheight, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
1119  uint8_t *imagepixels = reinterpret_cast<uint8_t*>(surface->pixels);
1120  // Copy the "reversed_image" memory to the "image" memory
1121  for (int32_t y = (sheight - 1); y >= 0; --y) {
1122  uint8_t *rowbegin = pixels + y * swidth * 3;
1123  uint8_t *rowend = rowbegin + swidth * 3;
1124 
1125  std::copy(rowbegin, rowend, imagepixels);
1126 
1127  // Advance a row in the output surface.
1128  imagepixels += surface->pitch;
1129  }
1130 
1131  SDL_UnlockSurface(surface);
1132  Image::saveAsPng(filename, *surface);
1133 
1134  SDL_FreeSurface(surface);
1135  delete[] pixels;
1136  }
1137 
1138  void RenderBackendOpenGL::captureScreen(const std::string& filename, uint32_t width, uint32_t height) {
1139  const uint32_t swidth = getWidth();
1140  const uint32_t sheight = getHeight();
1141  const bool same_size = (width == swidth && height == sheight);
1142 
1143  if (width < 1 || height < 1) {
1144  return;
1145  }
1146 
1147  if (same_size) {
1148  captureScreen(filename);
1149  return;
1150  }
1151 
1152  uint8_t *pixels;
1153  // create source surface
1154  SDL_Surface* src = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, sheight, 32,
1155  RMASK, GMASK, BMASK, AMASK);
1156 
1157  if (!src) {
1158  return;
1159  }
1160 
1161  if (SDL_MUSTLOCK(src)) {
1162  SDL_LockSurface(src);
1163  }
1164  pixels = new uint8_t[swidth * sheight * 4];
1165  glReadPixels(0, 0, swidth, sheight, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
1166 
1167  uint8_t* imagepixels = reinterpret_cast<uint8_t*>(src->pixels);
1168  // Copy the "reversed_image" memory to the "image" memory
1169  for (int32_t y = (sheight - 1); y >= 0; --y) {
1170  uint8_t *rowbegin = pixels + y * swidth * 4;
1171  uint8_t *rowend = rowbegin + swidth * 4;
1172 
1173  std::copy(rowbegin, rowend, imagepixels);
1174 
1175  // Advance a row in the output surface.
1176  imagepixels += src->pitch;
1177  }
1178 
1179  // create destination surface
1180  SDL_Surface* dst = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,
1181  RMASK, GMASK, BMASK, AMASK);
1182 
1183  uint32_t* src_pointer = static_cast<uint32_t*>(src->pixels);
1184  uint32_t* src_help_pointer = src_pointer;
1185  uint32_t* dst_pointer = static_cast<uint32_t*>(dst->pixels);
1186 
1187  int32_t x, y, *sx_ca, *sy_ca;
1188  int32_t sx = static_cast<int32_t>(0xffff * src->w / dst->w);
1189  int32_t sy = static_cast<int32_t>(0xffff * src->h / dst->h);
1190  int32_t sx_c = 0;
1191  int32_t sy_c = 0;
1192 
1193  // Allocates memory and calculates row wide&height
1194  int32_t* sx_a = new int32_t[dst->w + 1];
1195  sx_ca = sx_a;
1196  for (x = 0; x <= dst->w; x++) {
1197  *sx_ca = sx_c;
1198  sx_ca++;
1199  sx_c &= 0xffff;
1200  sx_c += sx;
1201  }
1202 
1203  int32_t* sy_a = new int32_t[dst->h + 1];
1204  sy_ca = sy_a;
1205  for (y = 0; y <= dst->h; y++) {
1206  *sy_ca = sy_c;
1207  sy_ca++;
1208  sy_c &= 0xffff;
1209  sy_c += sy;
1210  }
1211  sy_ca = sy_a;
1212 
1213  // Transfers the image data
1214 
1215  if (SDL_MUSTLOCK(dst)) {
1216  SDL_LockSurface(dst);
1217  }
1218 
1219  for (y = 0; y < dst->h; y++) {
1220  src_pointer = src_help_pointer;
1221  sx_ca = sx_a;
1222  for (x = 0; x < dst->w; x++) {
1223  *dst_pointer = *src_pointer;
1224  sx_ca++;
1225  src_pointer += (*sx_ca >> 16);
1226  dst_pointer++;
1227  }
1228  sy_ca++;
1229  src_help_pointer = (uint32_t*)((uint8_t*)src_help_pointer + (*sy_ca >> 16) * src->pitch);
1230  }
1231 
1232  if (SDL_MUSTLOCK(dst)) {
1233  SDL_UnlockSurface(dst);
1234  }
1235  if (SDL_MUSTLOCK(src)) {
1236  SDL_UnlockSurface(src);
1237  }
1238 
1239  Image::saveAsPng(filename, *dst);
1240 
1241  // Free memory
1242  SDL_FreeSurface(src);
1243  SDL_FreeSurface(dst);
1244  delete[] sx_a;
1245  delete[] sy_a;
1246  delete[] pixels;
1247  }
1248 
1249  void RenderBackendOpenGL::setClipArea(const Rect& cliparea, bool clear) {
1250  glScissor(cliparea.x, getHeight() - cliparea.y - cliparea.h, cliparea.w, cliparea.h);
1251  if (clear) {
1252  if (m_isbackgroundcolor) {
1253  float red = float(m_backgroundcolor.r/255.0);
1254  float green = float(m_backgroundcolor.g/255.0);
1255  float blue = float(m_backgroundcolor.b/255.0);
1256  glClearColor(red, green, blue, 0.0);
1257  m_isbackgroundcolor = false;
1258  }
1259  glClear(GL_COLOR_BUFFER_BIT);
1260  }
1261  }
1262 
1264  // flush down what we batched for the old target
1266 
1267  m_img_target = img;
1268  m_target_discard = discard;
1269 
1270  // to render on something, we need to make sure its loaded already in gpu memory
1273 
1274  GLImage* glimage = static_cast<GLImage*>(m_img_target.get());
1275 
1276  GLuint targetid = glimage->getTexId();
1279 
1280  // quick & dirty hack for attaching compressed texture
1281  if(glimage->isCompressed()) {
1282  bindTexture(targetid);
1283  GLubyte* pixels = new GLubyte[w*h*4];
1284  // here we get decompressed pixels
1285  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1286  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1287  delete [] pixels;
1288  glimage->setCompressed(false);
1289  }
1290 
1291  // can we use fbo?
1292  if (GLEE_EXT_framebuffer_object && m_useframebuffer) {
1293  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo_id);
1294  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
1295  GL_TEXTURE_2D, targetid, 0);
1296  }
1297 
1298  glViewport(0, 0, w, h);
1299  glMatrixMode(GL_PROJECTION);
1300  glLoadIdentity();
1301  // invert top with bottom
1302  glOrtho(0, w, 0, h, -1, 1);
1303  glMatrixMode(GL_MODELVIEW);
1304  // because of inversion 2 lines above we need to also invert culling faces
1305  glCullFace(GL_FRONT);
1306 
1307  if (m_target_discard) {
1308  glClear(GL_COLOR_BUFFER_BIT);
1309  } else if (!m_target_discard && (!GLEE_EXT_framebuffer_object || !m_useframebuffer)) {
1310  // if we wanna just add something to render target, we need to first render previous contents
1311  addImageToArray(targetid, m_img_target->getArea(),
1312  static_cast<GLImage*>(m_img_target.get())->getTexCoords(), 255, 0);
1313  }
1314  }
1315 
1317  assert(m_target != m_screen);
1318 
1319  // flush down what we batched
1321 
1322  if (GLEE_EXT_framebuffer_object && m_useframebuffer) {
1323  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1324  } else {
1325  bindTexture(0, static_cast<GLImage*>(m_img_target.get())->getTexId());
1326  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0,
1328  }
1329 
1330  m_target = m_screen;
1331  glViewport(0, 0, m_screen->w, m_screen->h);
1332  glMatrixMode(GL_PROJECTION);
1333  glLoadIdentity();
1334  glOrtho(0, m_screen->w, m_screen->h, 0, -1, 1);
1335  glMatrixMode(GL_MODELVIEW);
1336  glCullFace(GL_BACK);
1337  }
1338 }
Abstract interface for all the renderbackends.
Definition: renderbackend.h:92
virtual void changeRenderInfos(uint16_t elements, int32_t src, int32_t dst, bool light, bool stentest, uint8_t stenref, GLConstants stenop, GLConstants stenfunc)
Dirty helper function to change the render infos.
SDL_Surface * m_target
T * get() const
allows direct access to underlying pointer
Definition: sharedptr.h:155
const uint32_t NULLMASK
Definition: fife_stdint.h:63
virtual void setScreenMode(const ScreenMode &mode)
Sets the mainscreen display mode.
static T Cos(T _val)
Definition: fife_math.h:216
virtual void setLighting(float red, float green, float blue)
Set colors for lighting.
Base Class for Images.
Definition: image.h:47
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.
virtual uint32_t getLightingModel() const
Gets the current light model.
T h
Height of the rectangle.
Definition: rect.h:93
Helper class to create log strings out from separate parts Usage: LMsg(&quot;some text&quot;) &lt;&lt; variable &lt;&lt; &quot;...
Definition: logger.h:82
SDL_PixelFormat m_rgba_format
T x
The X Coordinate.
Definition: rect.h:84
uint32_t getHeight() const
void setCompressed(bool compressed)
Definition: glimage.h:75
uint32_t getSDLFlags() const
Returns the SDL flags used when testing this mode.
Definition: devicecaps.h:74
virtual void renderVertexArrays()
Render the Vertex Arrays, only for primitives (points, lines,...)
void disableTextures(uint32_t texUnit)
static void saveAsPng(const std::string &filename, const SDL_Surface &surface)
Saves the SDL_Surface to png format.
Definition: image.cpp:226
virtual void init(const std::string &driver)
Initializes the backend.
uint16_t getBPP() const
Returns the number of bits per pixel this mode uses.
Definition: devicecaps.h:70
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.
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.
const uint32_t RMASK
Definition: fife_stdint.h:53
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.
static Logger _log(LM_AUDIO)
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.
void setVertexPointer(GLsizei stride, const GLvoid *ptr)
virtual void setClipArea(const Rect &cliparea, bool clear)
Sets given clip area into image.
GLuint getTexId() const
Definition: glimage.cpp:417
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.
const uint32_t AMASK
Definition: fife_stdint.h:56
void setStencilTest(uint8_t stencil_ref, GLenum stencil_op, GLenum stencil_func)
const Rect & getArea() const
Definition: image.cpp:171
void enableTextures(uint32_t texUnit)
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.
virtual void setLightingModel(uint32_t lighting)
Initializes the light.
virtual Image * createImage(IResourceLoader *loader=0)
uint32_t getHeight() const
Definition: image.cpp:155
void setEnvironmentalColor(const uint8_t *rgba)
unsigned char uint8_t
Definition: core.h:38
virtual void resetLighting()
Reset lighting with default values.
std::vector< RenderObject > m_render_objects
const uint32_t GMASK
Definition: fife_stdint.h:54
virtual void captureScreen(const std::string &filename)
Creates a Screenshot and saves it to a file.
SDL_Surface * getSurface()
Definition: image.h:91
virtual void startFrame()
Called when a new frame starts.
static T Sin(T _val)
Definition: fife_math.h:266
std::vector< renderData2T > m_render_datas2T
virtual void clearBackBuffer()
Forces a clear of the backbuffer.
virtual void changeBlending(int32_t scr, int32_t dst)
Change the Blendingmodel.
bool isCompressed() const
Definition: glimage.h:74
uint16_t getHeight() const
Returns the height of the screen mode.
Definition: devicecaps.h:66
const uint32_t BMASK
Definition: fife_stdint.h:55
struct FIFE::RenderBackendOpenGL::currentState m_state
uint32_t getWidth() const
Definition: image.cpp:146
unsigned short uint16_t
Definition: core.h:39
T y
The Y Coordinate.
Definition: rect.h:87
uint16_t getWidth() const
Returns the width of the screen mode.
Definition: devicecaps.h:60
SDL_Surface * m_screen
static num_type twoPi()
Definition: fife_math.h:134
virtual void detachRenderTarget()
Detaches current render surface.
SDL_Color m_backgroundcolor
#define FL_LOG(logger, msg)
Definition: logger.h:71
void setTexCoordPointer(uint32_t texUnit, GLsizei stride, const GLvoid *ptr)
uint32_t getWidth() const
virtual void endFrame()
Called when a frame is finished and ready to be displayed.
void setAlphaTest(float ref_alpha)
virtual void createMainScreen(const ScreenMode &mode, const std::string &title, const std::string &icon)
Creates the mainscreen (the display window).
virtual void forceLoadInternal()=0
Forces to load the image into internal memory of GPU.
Implements an Image using OpenGL.
Definition: glimage.h:53
RenderBackendOpenGL(const SDL_Color &colorkey)
std::vector< renderData > m_render_datas
void setColorPointer(GLsizei stride, const GLvoid *ptr)
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.
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.
ScreenMode m_screenMode
virtual void attachRenderTarget(ImagePtr &img, bool discard)
Attaches given image as a new render surface.
RenderObject(GLenum m, uint16_t s, uint32_t t=0)
void deinit()
Performs cleanup actions.
unsigned int uint32_t
Definition: core.h:40
virtual void startFrame()
Called when a new frame starts.
T w
Width of the rectangle.
Definition: rect.h:90
void bindTexture(uint32_t texUnit, GLuint texId)
virtual void endFrame()
Called when a frame is finished and ready to be displayed.
virtual void resetStencilBuffer(uint8_t buffer)
Reset stencil buffer with given value.
virtual const std::string & getName() const
The name of the renderbackend.