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 t1=0, uint32_t t2=0):
48  mode(m),
49  size(s),
50  texture_id(t1),
51  overlay_id(t2),
52  src(4),
53  dst(5),
54  light(true),
55  stencil_test(false),
56  color(true),
58  stencil_ref(0),
59  stencil_op(0),
60  stencil_func(0) {}
61 
62  GLenum mode;
66  int32_t src;
67  int32_t dst;
68  bool light;
70  bool color;
73  GLenum stencil_op;
74  GLenum stencil_func;
76  };
77 
78  RenderBackendOpenGL::RenderBackendOpenGL(const SDL_Color& colorkey)
79  : RenderBackend(colorkey), m_maskOverlay(0){
80 
81  m_state.tex_enabled[0] = false;
82  m_state.tex_enabled[1] = false;
83  m_state.tex_enabled[2] = false;
84  m_state.tex_enabled[3] = false;
85  m_state.texture[0] = 0;
86  m_state.texture[1] = 0;
87  m_state.texture[2] = 0;
88  m_state.texture[3] = 0;
89  m_state.active_tex = 0;
90  m_state.alpha_test = 0.0;
93  m_state.tex_pointer[0] = 0;
94  m_state.tex_pointer[1] = 0;
95  m_state.tex_pointer[2] = 0;
96  m_state.tex_pointer[3] = 0;
98 
99  m_state.sten_enabled = false;
100  m_state.sten_ref = 0;
101  m_state.sten_buf = 0;
102  m_state.sten_op = 0;
103  m_state.sten_func = 0;
104 
105  m_state.lightmodel = 0;
106  m_state.light_enabled = false;
107 
108  m_state.env_color[0] = 0;
109  m_state.env_color[1] = 0;
110  m_state.env_color[2] = 0;
111  m_state.env_color[3] = 0;
112  m_state.blend_src = GL_SRC_ALPHA;
113  m_state.blend_dst = GL_ONE_MINUS_SRC_ALPHA;
114  m_state.alpha_enabled = true;
115  m_state.scissor_test = true;
116  m_state.depth_enabled = true;
117  m_state.color_enabled = true;
118  }
119 
121  glDeleteTextures(1, &m_maskOverlay);
122  if(GLEE_EXT_framebuffer_object && m_useframebuffer) {
123  glDeleteFramebuffers(1, &m_fbo_id);
124  }
125  deinit();
126  }
127 
128  const std::string& RenderBackendOpenGL::getName() const {
129  static std::string backend_name = "OpenGL";
130  return backend_name;
131  }
132 
133  void RenderBackendOpenGL::init(const std::string& driver) {
134  // note: driver has no affect on the opengl renderer so do nothing with it here.
135  Uint32 flags = SDL_INIT_VIDEO;
136  if (SDL_InitSubSystem(flags) < 0)
137  throw SDLException(SDL_GetError());
138  // defines buffer sizes
139  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
140  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
141  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
142  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
143  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
144  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
145  SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
146 
147  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // temporary hack
148  }
149 
152  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
154  }
155 
156  void RenderBackendOpenGL::createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon){
157  if(icon != "") {
158  SDL_Surface *img = IMG_Load(icon.c_str());
159  if(img != NULL) {
160  SDL_WM_SetIcon(img, 0);
161  SDL_FreeSurface(img);
162  }
163  }
164 
165  SDL_WM_SetCaption(title.c_str(), 0);
166  setScreenMode(mode);
167  }
168 
170  uint16_t width = mode.getWidth();
171  uint16_t height = mode.getHeight();
172  uint16_t bitsPerPixel = mode.getBPP();
173  uint32_t flags = mode.getSDLFlags();
174 
175  if (bitsPerPixel != 0) {
176  uint16_t bpp = SDL_VideoModeOK(width, height, bitsPerPixel, flags);
177  if (!bpp){
178  throw SDLException("Selected video mode not supported!");
179  }
180  }
181 
182  if(m_screen) {
183  SDL_FreeSurface(m_screen);
184  }
185  m_screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags);
186  if( !m_screen ) {
187  throw SDLException("Unable to set video mode selected!");
188  }
189  m_target = m_screen;
190 
191  FL_LOG(_log, LMsg("RenderBackendOpenGL")
192  << "Videomode " << width << "x" << height
193  << " at " << int32_t(bitsPerPixel) << " bpp");
194 
195  m_rgba_format = *(m_screen->format);
196  m_rgba_format.Rmask = RMASK;
197  m_rgba_format.Gmask = GMASK;
198  m_rgba_format.Bmask = BMASK;
199  m_rgba_format.Amask = AMASK;
200 
201  //update the screen mode with the actual flags used
202  m_screenMode = ScreenMode(width,
203  height,
204  bitsPerPixel,
205  m_screen->flags);
206 
207  if (!m_screen) {
208  throw SDLException(SDL_GetError());
209  }
210 
211  glViewport(0, 0, width, height);
212  glMatrixMode(GL_PROJECTION);
213  glLoadIdentity();
214  glOrtho(0, width, height, 0, -100, 100);
215  glMatrixMode(GL_MODELVIEW);
216  glLoadIdentity();
217 
218  glEnable(GL_CULL_FACE);
219  glFrontFace(GL_CCW);
220  glCullFace(GL_BACK);
221 
222  glPixelStorei(GL_PACK_ALIGNMENT, 1);
223  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
224 
225  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
226  glClearDepth(1.0f);
227  glClearStencil(0);
228 
229  glEnable(GL_BLEND);
230  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
231 
233 
234  glEnable(GL_DEPTH_TEST);
235  glDepthFunc(GL_LEQUAL);
236 
237  glEnable(GL_SCISSOR_TEST);
238 
239  glEnableClientState(GL_COLOR_ARRAY);
240  glEnableClientState(GL_VERTEX_ARRAY);
241 
243 
244  glPointSize(1.0);
245  glLineWidth(1.0);
246 
247  if(GLEE_EXT_framebuffer_object && m_useframebuffer) {
248  glGenFramebuffers(1, &m_fbo_id);
249  }
250 
252  if (GLEE_EXT_texture_filter_anisotropic) {
253  GLint largest = 0;
254  glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest);
255  m_maxAnisotropy = static_cast<int32_t>(largest);
256  } else {
257  // if not available use trilinear filter
258  m_maxAnisotropy = 0;
260  }
261  }
262  // currently unused, 1000 objects x 400 textures x 4 renderDataZ
263  //m_renderZ_datas.resize(1600000);
264  }
265 
268  }
269 
271  SDL_GL_SwapBuffers();
273  }
274 
276  return new GLImage(loader);
277  }
278 
279  Image* RenderBackendOpenGL::createImage(const std::string& name, IResourceLoader* loader) {
280  return new GLImage(name, loader);
281  }
282 
283  Image* RenderBackendOpenGL::createImage(SDL_Surface* surface) {
284  // Given an abritary surface, we must convert it to the format GLImage will understand.
285  // It's easiest to let SDL do this for us.
286 
287  // Uh. Gotta love this :-)
288  // Check for colorkey too?
289  // Leave out the loss/shift checks?
290  if (32 == surface->format->BitsPerPixel
291  && m_rgba_format.Rmask == surface->format->Rmask
292  && m_rgba_format.Gmask == surface->format->Gmask
293  && m_rgba_format.Bmask == surface->format->Bmask
294  && m_rgba_format.Amask == surface->format->Amask
295  && m_rgba_format.Rshift == surface->format->Rshift
296  && m_rgba_format.Gshift == surface->format->Gshift
297  && m_rgba_format.Bshift == surface->format->Bshift
298  && m_rgba_format.Ashift == surface->format->Ashift
299  && m_rgba_format.Rloss == surface->format->Rloss
300  && m_rgba_format.Gloss == surface->format->Gloss
301  && m_rgba_format.Bloss == surface->format->Bloss
302  && m_rgba_format.Aloss == surface->format->Aloss
303  && surface->flags & SDL_SRCALPHA ) {
304 
305  return new GLImage(surface);
306  }
307 
308  uint8_t bpp = m_rgba_format.BitsPerPixel;
309  m_rgba_format.BitsPerPixel = 32;
310  SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA);
311  m_rgba_format.BitsPerPixel = bpp;
312  GLImage* image = new GLImage(conv);
313 
314  SDL_FreeSurface(surface);
315  return image;
316  }
317 
318  Image* RenderBackendOpenGL::createImage(const std::string& name, SDL_Surface* surface) {
319  // Given an abritary surface, we must convert it to the format GLImage will understand.
320  // It's easiest to let SDL do this for us.
321 
322  // Uh. Gotta love this :-)
323  // Check for colorkey too?
324  // Leave out the loss/shift checks?
325  if (32 == surface->format->BitsPerPixel
326  && m_rgba_format.Rmask == surface->format->Rmask
327  && m_rgba_format.Gmask == surface->format->Gmask
328  && m_rgba_format.Bmask == surface->format->Bmask
329  && m_rgba_format.Amask == surface->format->Amask
330  && m_rgba_format.Rshift == surface->format->Rshift
331  && m_rgba_format.Gshift == surface->format->Gshift
332  && m_rgba_format.Bshift == surface->format->Bshift
333  && m_rgba_format.Ashift == surface->format->Ashift
334  && m_rgba_format.Rloss == surface->format->Rloss
335  && m_rgba_format.Gloss == surface->format->Gloss
336  && m_rgba_format.Bloss == surface->format->Bloss
337  && m_rgba_format.Aloss == surface->format->Aloss
338  && surface->flags & SDL_SRCALPHA ) {
339 
340  return new GLImage(name, surface);
341  }
342 
343  uint8_t bpp = m_rgba_format.BitsPerPixel;
344  m_rgba_format.BitsPerPixel = 32;
345  SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA);
346  m_rgba_format.BitsPerPixel = bpp;
347  GLImage* image = new GLImage(name, conv);
348 
349  SDL_FreeSurface(surface);
350  return image;
351  }
352 
354  return new GLImage(data, width, height);
355  }
356 
357  Image* RenderBackendOpenGL::createImage(const std::string& name, const uint8_t* data, uint32_t width, uint32_t height) {
358  return new GLImage(name, data, width, height);
359  }
360 
362  if (m_state.lightmodel != lighting) {
363  if (m_state.lightmodel != 0) {
364  disableLighting();
365  glDisable(GL_COLOR_MATERIAL);
366  } else if (lighting != 0) {
367  enableLighting();
368  glEnable(GL_LIGHT0);
369  glColorMaterial(GL_FRONT, GL_DIFFUSE);
370  glEnable(GL_COLOR_MATERIAL);
371  }
372  m_state.lightmodel = lighting;
373  }
374  }
375 
377  return m_state.lightmodel;
378  }
379 
381  if(m_state.tex_enabled[texUnit] == false) {
382  if(m_state.active_tex != texUnit) {
383  m_state.active_tex = texUnit;
384  glActiveTexture(GL_TEXTURE0 + texUnit);
385  }
386  if (m_state.active_client_tex != texUnit) {
387  m_state.active_client_tex = texUnit;
388  glClientActiveTexture(GL_TEXTURE0 + texUnit);
389  }
390  m_state.tex_enabled[texUnit] = true;
391 
392  glEnable(GL_TEXTURE_2D);
393  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
394  }
395  }
396 
398  if(m_state.tex_enabled[texUnit] == true) {
399  if(m_state.active_tex != texUnit) {
400  m_state.active_tex = texUnit;
401  glActiveTexture(GL_TEXTURE0 + texUnit);
402  }
403  if (m_state.active_client_tex != texUnit) {
404  m_state.active_client_tex = texUnit;
405  glClientActiveTexture(GL_TEXTURE0 + texUnit);
406  }
407  m_state.tex_enabled[texUnit] = false;
408 
409  glDisable(GL_TEXTURE_2D);
410  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
411  }
412  }
413 
414  void RenderBackendOpenGL::bindTexture(uint32_t texUnit, GLuint texId) {
415  enableTextures(texUnit);
416 
417  if(m_state.texture[texUnit] != texId) {
418  if(m_state.active_tex != texUnit) {
419  m_state.active_tex = texUnit;
420  glActiveTexture(GL_TEXTURE0 + texUnit);
421  }
422  if (m_state.active_client_tex != texUnit) {
423  m_state.active_client_tex = texUnit;
424  glClientActiveTexture(GL_TEXTURE0 + texUnit);
425  }
426  m_state.texture[texUnit] = texId;
427  glBindTexture(GL_TEXTURE_2D, texId);
428  }
429  }
430 
431  void RenderBackendOpenGL::bindTexture(GLuint texId) {
432  if(m_state.texture[m_state.active_tex] != texId) {
434  glBindTexture(GL_TEXTURE_2D, texId);
435  }
436  }
437 
439  if (m_state.lightmodel != 0 && !m_state.light_enabled) {
440  glEnable(GL_LIGHTING);
441  m_state.light_enabled = true;
442  }
443  }
444 
446  if (m_state.lightmodel != 0 && m_state.light_enabled) {
447  glDisable(GL_LIGHTING);
448  m_state.light_enabled = false;
449  }
450  }
451 
452  void RenderBackendOpenGL::setLighting(float red, float green, float blue) {
453  if (m_state.lightmodel != 0) {
454  GLfloat lightDiffuse[] = {red, green, blue, 1.0f};
455  glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
456  }
457  }
458 
460  if (m_state.lightmodel != 0) {
461  setLighting(1.0, 1.0, 1.0);
462  }
463  }
464 
466  if (!m_state.sten_enabled) {
467  glEnable(GL_STENCIL_TEST);
468  m_state.sten_enabled = true;
469  }
470  }
471 
473  if (m_state.sten_enabled) {
474  glDisable(GL_STENCIL_TEST);
475  m_state.sten_enabled = false;
476  }
477  }
478 
479  void RenderBackendOpenGL::setStencilTest(uint8_t stencil_ref, GLenum stencil_op, GLenum stencil_func) {
481  if(m_state.sten_op != stencil_op) {
482  m_state.sten_op = stencil_op;
483  glStencilOp(GL_KEEP, GL_KEEP, m_state.sten_op);
484  }
485 
486  if(m_state.sten_ref != stencil_ref || m_state.sten_func != stencil_func) {
487  m_state.sten_ref = stencil_ref;
488  m_state.sten_func = stencil_func;
489  glStencilFunc(m_state.sten_func, stencil_ref, 0xff);
490  }
491  }
492 
494  if (buffer != m_state.sten_buf) {
495  m_state.sten_buf = buffer;
496  glClearStencil(buffer);
497  }
499  glClear(GL_STENCIL_BUFFER_BIT);
501  }
502 
504  return m_state.sten_ref;
505  }
506 
508  if (!m_state.alpha_enabled) {
509  glEnable(GL_ALPHA_TEST);
510  m_state.alpha_enabled = true;
511  }
512  }
513 
515  if (m_state.alpha_enabled) {
516  glDisable(GL_ALPHA_TEST);
517  m_state.alpha_enabled = false;
518  }
519  }
520 
521  void RenderBackendOpenGL::setAlphaTest(float ref_alpha) {
522  enableAlphaTest();
523  if (!Mathf::Equal(m_state.alpha_test, ref_alpha)) {
524  m_state.alpha_test = ref_alpha;
525  glAlphaFunc(GL_GREATER, ref_alpha);
526  }
527  }
528 
530  if (!m_state.depth_enabled) {
531  glEnable(GL_DEPTH_TEST);
532  m_state.depth_enabled = true;
533  }
534  }
535 
537  if (m_state.depth_enabled) {
538  glDisable(GL_DEPTH_TEST);
539  m_state.depth_enabled = false;
540  }
541  }
542 
544  if (!m_state.color_enabled) {
545  glEnableClientState(GL_COLOR_ARRAY);
546  m_state.color_enabled = true;
547  }
548  }
549 
551  if (m_state.color_enabled) {
552  glDisableClientState(GL_COLOR_ARRAY);
553  glColor4ub(255,255,255,255);
554  m_state.color_enabled = false;
555  }
556  }
557 
559  if (memcmp(m_state.env_color, rgba, sizeof(uint8_t) * 4) || m_state.active_tex != texUnit) {
560 
561  memcpy(m_state.env_color, rgba, sizeof(uint8_t) * 4);
562  GLfloat rgbaf[4] = {
563  static_cast<float>(m_state.env_color[0]) / 255.0f,
564  static_cast<float>(m_state.env_color[1]) / 255.0f,
565  static_cast<float>(m_state.env_color[2]) / 255.0f,
566  static_cast<float>(m_state.env_color[3]) / 255.0f};
567 
568  if(m_state.active_tex != texUnit) {
569  m_state.active_tex = texUnit;
570  glActiveTexture(GL_TEXTURE0 + texUnit);
571  m_state.active_client_tex = texUnit;
572  glClientActiveTexture(GL_TEXTURE0 + texUnit);
573  }
574 
575  glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgbaf);
576  }
577  }
578 
579  void RenderBackendOpenGL::setVertexPointer(GLint size, GLsizei stride, const GLvoid* ptr) {
580  if(m_state.vertex_pointer != ptr || m_state.vertex_pointer_size != size) {
581  m_state.vertex_pointer = ptr;
583  glVertexPointer(size, GL_FLOAT, stride, ptr);
584  }
585  }
586 
587  void RenderBackendOpenGL::setColorPointer(GLsizei stride, const GLvoid* ptr) {
588  if(m_state.color_pointer != ptr) {
589  m_state.color_pointer = ptr;
590  glColorPointer(4, GL_UNSIGNED_BYTE, stride, ptr);
591  }
592  }
593 
594  void RenderBackendOpenGL::setTexCoordPointer(uint32_t texUnit, GLsizei stride, const GLvoid* ptr) {
595  if(m_state.tex_pointer[texUnit] != ptr) {
596  if(m_state.active_tex != texUnit) {
597  m_state.active_tex = texUnit;
598  glActiveTexture(GL_TEXTURE0 + texUnit);
599  }
600  if (m_state.active_client_tex != texUnit) {
601  m_state.active_client_tex = texUnit;
602  glClientActiveTexture(GL_TEXTURE0 + texUnit);
603  }
604  m_state.tex_pointer[texUnit] = ptr;
605  glTexCoordPointer(2, GL_FLOAT, stride, ptr);
606  }
607  }
608 
610  if(m_state.scissor_test == false) {
611  m_state.scissor_test = true;
612  glEnable(GL_SCISSOR_TEST);
613  }
614  }
615 
617  if(m_state.scissor_test == true) {
618  m_state.scissor_test = false;
619  glDisable(GL_SCISSOR_TEST);
620  }
621  }
622 
623  void RenderBackendOpenGL::changeBlending(int32_t src, int32_t dst) {
624  GLenum src_fact;
625  GLenum dst_fact;
626 
627  switch(src) {
628  case 0 : src_fact = GL_ZERO; break;
629  case 1 : src_fact = GL_ONE; break;
630  case 2 : src_fact = GL_DST_COLOR; break;
631  case 3 : src_fact = GL_ONE_MINUS_DST_COLOR; break;
632  case 4 : src_fact = GL_SRC_ALPHA; break;
633  case 5 : src_fact = GL_ONE_MINUS_SRC_ALPHA; break;
634  case 6 : src_fact = GL_DST_ALPHA; break;
635  case 7 : src_fact = GL_ONE_MINUS_DST_ALPHA; break;
636 
637  default : src_fact = GL_DST_COLOR; break;
638  }
639 
640  switch(dst) {
641  case 0 : dst_fact = GL_ZERO; break;
642  case 1 : dst_fact = GL_ONE; break;
643  case 2 : dst_fact = GL_SRC_COLOR; break;
644  case 3 : dst_fact = GL_ONE_MINUS_SRC_COLOR; break;
645  case 4 : dst_fact = GL_SRC_ALPHA; break;
646  case 5 : dst_fact = GL_ONE_MINUS_SRC_ALPHA; break;
647  case 6 : dst_fact = GL_DST_ALPHA; break;
648  case 7 : dst_fact = GL_ONE_MINUS_DST_ALPHA; break;
649 
650  default : dst_fact = GL_SRC_ALPHA; break;
651  }
652 
653  if (m_state.blend_src != src_fact || m_state.blend_dst != dst_fact) {
654  m_state.blend_src = src_fact;
655  m_state.blend_dst = dst_fact;
656  glBlendFunc(src_fact, dst_fact);
657  }
658  }
659 
660  void RenderBackendOpenGL::changeRenderInfos(RenderDataType type, uint16_t elements, int32_t src, int32_t dst, bool light,
661  bool stentest, uint8_t stenref, GLConstants stenop, GLConstants stenfunc, OverlayType otype) {
662 
663  uint16_t count = 0;
664  switch (type) {
665  case RENDER_DATA_WITHOUT_Z: {
666  uint32_t size = m_renderObjects.size();
667  while (count != elements) {
668  ++count;
669  RenderObject& r = m_renderObjects.at(size-count);
670 
671  r.src = src;
672  r.dst = dst;
673  r.light = light;
674  r.overlay_type = otype;
675  if (stentest) {
676  r.stencil_test = stentest;
677  r.stencil_ref = stenref;
678  r.stencil_op = stenop;
679  r.stencil_func = stenfunc;
680  }
681  }
682  } break;
683  case RENDER_DATA_TEXTURE_Z: {
684  // not needed currently
685  } break;
686  case RENDER_DATA_TEXCOLOR_Z : {
687  // not needed currently
688  } break;
691  while (count != elements) {
692  ++count;
693  RenderObject& r = m_renderMultitextureObjectsZ.at(size-count);
694  // only overlay_type is important
695  r.src = src;
696  r.dst = dst;
697  r.light = light;
698  r.overlay_type = otype;
699  if (stentest) {
700  r.stencil_test = stentest;
701  r.stencil_ref = stenref;
702  r.stencil_op = stenop;
703  r.stencil_func = stenfunc;
704  }
705  }
706  } break;
707  default: {
708  // nothing
709  } break;
710  }
711  }
712 
714  // bools to indicate changes
715  bool type = false;
716  bool texture = false;
717  bool blending = false;
718  bool light = false;
719  bool stencil = false;
720  bool color = false;
721  bool mt = false;
722  bool render = false;
723 
724  // render mode
725  GLenum mode = GL_QUADS;
726  // texture id
727  uint32_t texture_id = 0;
728  uint32_t texture_id2 = 0;
729  // src blending mode
730  int32_t src = 4;
731  // dst blending mode
732  int32_t dst = 5;
733  // overlay type
734  OverlayType overlay_type = OVERLAY_TYPE_NONE;
735  // overlay color
736  uint8_t rgba[4] = {0};
737 
738  // array indices
739  int32_t indexP = 0;
740  int32_t indexT = 0;
741  int32_t indexTC = 0;
742  int32_t index2TC = 0;
743  // elements to render
744  uint32_t elementsP = 0;
745  uint32_t elementsT = 0;
746  uint32_t elementsTC = 0;
747  uint32_t elements2TC = 0;
748 
749  int32_t* currentIndex = 0;
750  uint32_t* currentElements = 0;
751 
752  //stride
753  const uint32_t strideP = sizeof(renderDataP);
754  const uint32_t strideT = sizeof(renderDataT);
755  const uint32_t strideTC = sizeof(renderDataTC);
756  const uint32_t stride2TC = sizeof(renderData2TC);
757 
758  // disable alpha and depth tests
761 
762  if (m_renderObjects[0].overlay_type == OVERLAY_TYPE_NONE) {
763  // texture without color/alpha
764  if (!m_renderObjects[0].color) {
765  // set pointer
767  setVertexPointer(2, strideT, &m_renderTextureDatas[0].vertex);
768  setTexCoordPointer(0, strideT, &m_renderTextureDatas[0].texel);
769  currentIndex = &indexT;
770  currentElements = &elementsT;
771  // texture with color/alpha
772  } else if (m_renderObjects[0].texture_id != 0){
773  // set pointer
775  setVertexPointer(2, strideTC, &m_renderTextureColorDatas[0].vertex);
776  setTexCoordPointer(0, strideTC, &m_renderTextureColorDatas[0].texel);
777  setColorPointer(strideTC, &m_renderTextureColorDatas[0].color);
778  currentIndex = &indexTC;
779  currentElements = &elementsTC;
780  // primitive
781  } else {
782  // set pointer
784  setVertexPointer(2, strideP, &m_renderPrimitiveDatas[0].vertex);
785  setColorPointer(strideP, &m_renderPrimitiveDatas[0].color);
786  currentIndex = &indexP;
787  currentElements = &elementsP;
788  }
789  // multitexture overlay
790  } else {
791  // set pointer
792  setVertexPointer(2, stride2TC, &m_renderMultitextureDatas[0].vertex);
793  setColorPointer(stride2TC, &m_renderMultitextureDatas[0].color);
794  setTexCoordPointer(0, stride2TC, &m_renderMultitextureDatas[0].texel);
795  currentIndex = &index2TC;
796  currentElements = &elements2TC;
797  }
798 
799  for(std::vector<RenderObject>::iterator ir = m_renderObjects.begin(); ir != m_renderObjects.end(); ++ir) {
800  RenderObject& ro = (*ir);
801 
802  // first we look for changes
803  if (ro.mode != mode) {
804  type = true;
805  render = true;
806  }
807  if (ro.texture_id != texture_id) {
808  texture = true;
809  render = true;
810  }
811  if (ro.color != m_state.color_enabled) {
812  color = true;
813  render = true;
814  }
815  if (ro.overlay_type != overlay_type ||
816  (ro.overlay_type != OVERLAY_TYPE_NONE && (memcmp(rgba, ro.rgba, sizeof(uint8_t) * 4) || ro.overlay_id != texture_id2))) {
817  mt = true;
818  render = true;
819  }
820  if (m_state.lightmodel) {
821  if (ro.src != src || ro.dst != dst) {
822  blending = true;
823  render = true;
824  }
825  if (ro.light != m_state.light_enabled) {
826  light = true;
827  render = true;
828  }
829  if (ro.stencil_test != m_state.sten_enabled) {
830  stencil = true;
831  render = true;
832  } else if (ro.stencil_test) {
833  if (ro.stencil_ref != m_state.sten_ref ||
834  ro.stencil_op != m_state.sten_op ||
836  stencil = true;
837  render = true;
838  }
839  }
840  }
841 
842  // if changes then we render all previously elements
843  if (render) {
844  if (*currentElements > 0) {
845  //render
846  glDrawArrays(mode, *currentIndex, *currentElements);
847  *currentIndex += *currentElements;
848  }
849  // switch mode
850  if (type) {
851  mode = ro.mode;
852  type = false;
853  }
854  // switch coloring
855  if (color) {
856  if (ro.color && !m_state.color_enabled) {
858  if (ro.overlay_type == OVERLAY_TYPE_NONE) {
859  if (ro.texture_id != 0) {
860  setVertexPointer(2, strideTC, &m_renderTextureColorDatas[0].vertex);
861  setTexCoordPointer(0, strideTC, &m_renderTextureColorDatas[0].texel);
862  setColorPointer(strideTC, &m_renderTextureColorDatas[0].color);
863  currentElements = &elementsTC;
864  currentIndex = &indexTC;
865  } else {
866  setVertexPointer(2, strideP, &m_renderPrimitiveDatas[0].vertex);
867  setColorPointer(strideP, &m_renderPrimitiveDatas[0].color);
868  currentElements = &elementsP;
869  currentIndex = &indexP;
870  }
871  }
872  } else if (!ro.color && m_state.color_enabled) {
874  if (ro.overlay_type == OVERLAY_TYPE_NONE) {
875  setVertexPointer(2, strideT, &m_renderTextureDatas[0].vertex);
876  setTexCoordPointer(0, strideT, &m_renderTextureDatas[0].texel);
877  currentElements = &elementsT;
878  currentIndex = &indexT;
879  }
880  }
881  color = false;
882  }
883  // multitexturing
884  if (mt) {
885  switch (ro.overlay_type) {
886  case OVERLAY_TYPE_NONE:
887  disableTextures(3);
888  disableTextures(2);
889  disableTextures(1);
890 
891  if (ro.texture_id != 0) {
892  enableTextures(0);
893  if (m_state.color_enabled) {
894  setVertexPointer(2, strideTC, &m_renderTextureColorDatas[0].vertex);
895  setTexCoordPointer(0, strideTC, &m_renderTextureColorDatas[0].texel);
896  setColorPointer(strideTC, &m_renderTextureColorDatas[0].color);
897  currentElements = &elementsTC;
898  currentIndex = &indexTC;
899  } else {
900  setVertexPointer(2, strideT, &m_renderTextureDatas[0].vertex);
901  setTexCoordPointer(0, strideT, &m_renderTextureDatas[0].texel);
902  currentIndex = &indexT;
903  currentElements = &elementsT;
904  }
905  } else {
906  setVertexPointer(2, strideP, &m_renderPrimitiveDatas[0].vertex);
907  setColorPointer(strideP, &m_renderPrimitiveDatas[0].color);
908  currentElements = &elementsP;
909  currentIndex = &indexP;
910  }
911  texture_id2 = 0;
912  break;
913  case OVERLAY_TYPE_COLOR:
914  disableTextures(3);
915  disableTextures(2);
918  enableTextures(0);
919 
920  // set pointer
921  setVertexPointer(2, stride2TC, &m_renderMultitextureDatas[0].vertex);
922  setColorPointer(stride2TC, &m_renderMultitextureDatas[0].color);
923  setTexCoordPointer(1, stride2TC, &m_renderMultitextureDatas[0].texel2);
924  setTexCoordPointer(0, stride2TC, &m_renderMultitextureDatas[0].texel);
925 
926  texture_id2 = m_maskOverlay;
927  currentElements = &elements2TC;
928  currentIndex = &index2TC;
929  break;
931  disableTextures(3);
932  disableTextures(1);
933  bindTexture(2, ro.overlay_id);
935  enableTextures(0);
936 
937  // set pointer
938  setVertexPointer(2, stride2TC, &m_renderMultitextureDatas[0].vertex);
939  setColorPointer(stride2TC, &m_renderMultitextureDatas[0].color);
940  setTexCoordPointer(2, stride2TC, &m_renderMultitextureDatas[0].texel2);
941  setTexCoordPointer(0, stride2TC, &m_renderMultitextureDatas[0].texel);
942 
943  texture_id2 = ro.overlay_id;
944  currentElements = &elements2TC;
945  currentIndex = &index2TC;
946  break;
948  disableTextures(2);
949  disableTextures(1);
950  bindTexture(3, ro.overlay_id);
952  enableTextures(0);
953 
954  // set pointer
955  setVertexPointer(2, stride2TC, &m_renderMultitextureDatas[0].vertex);
956  setColorPointer(stride2TC, &m_renderMultitextureDatas[0].color);
957  setTexCoordPointer(3, stride2TC, &m_renderMultitextureDatas[0].texel2);
958  setTexCoordPointer(0, stride2TC, &m_renderMultitextureDatas[0].texel);
959 
960  texture_id2 = ro.overlay_id;
961  currentElements = &elements2TC;
962  currentIndex = &index2TC;
963  break;
964  }
965  memcpy(rgba, ro.rgba, sizeof(uint8_t) * 4);
966  overlay_type = ro.overlay_type;
967  mt = false;
968  }
969  // switch texturing
970  if (texture) {
971  if (ro.texture_id != 0) {
972  bindTexture(0, ro.texture_id);
973  texture_id = ro.texture_id;
974  if (ro.overlay_type == OVERLAY_TYPE_NONE) {
975  if (m_state.color_enabled) {
976  setVertexPointer(2, strideTC, &m_renderTextureColorDatas[0].vertex);
977  setTexCoordPointer(0, strideTC, &m_renderTextureColorDatas[0].texel);
978  setColorPointer(strideTC, &m_renderTextureColorDatas[0].color);
979  currentElements = &elementsTC;
980  currentIndex = &indexTC;
981  } else {
982  setVertexPointer(2, strideT, &m_renderTextureDatas[0].vertex);
983  setTexCoordPointer(0, strideT, &m_renderTextureDatas[0].texel);
984  currentElements = &elementsT;
985  currentIndex = &indexT;
986  }
987  }
988  } else {
989  disableTextures(0);
990  texture_id = 0;
991  if (ro.overlay_type == OVERLAY_TYPE_NONE) {
992  setVertexPointer(2, strideP, &m_renderPrimitiveDatas[0].vertex);
993  setColorPointer(strideP, &m_renderPrimitiveDatas[0].color);
994  currentElements = &elementsP;
995  currentIndex = &indexP;
996  }
997  }
998  texture = false;
999  }
1000 
1001  // set element to current size
1002  *currentElements = ro.size;
1003 
1004  // if lighting is enabled we have to consider a few more values
1005  if (m_state.lightmodel) {
1006  // change blending
1007  if (blending) {
1008  src = ro.src;
1009  dst = ro.dst;
1010  changeBlending(ro.src, ro.dst);
1011  blending = false;
1012  }
1013  // change light
1014  if (light) {
1015  if (ro.light && !m_state.light_enabled) {
1016  enableLighting();
1017  } else if (!ro.light && m_state.light_enabled) {
1018  disableLighting();
1019  }
1020  light = false;
1021  }
1022  // change stencil
1023  if (stencil) {
1024  if (ro.stencil_test) {
1026  setAlphaTest(0.0);
1027  } else {
1028  disableAlphaTest();
1030  }
1031  stencil = false;
1032  }
1033  }
1034 
1035  render = false;
1036  } else {
1037  // else add the element
1038  *currentElements += ro.size;
1039  }
1040  }
1041  // render
1042  glDrawArrays(mode, *currentIndex, *currentElements);
1043 
1044  // reset all states
1045  if (overlay_type != OVERLAY_TYPE_NONE) {
1046  disableTextures(3);
1047  disableTextures(2);
1048  disableTextures(1);
1049  }
1050  disableTextures(0);
1051  enableColorArray();
1052 
1053  if (m_state.lightmodel != 0) {
1054  changeBlending(4, 5);
1055  disableLighting();
1057  disableAlphaTest();
1058  }
1059 
1060  m_renderPrimitiveDatas.clear();
1061  m_renderTextureDatas.clear();
1062  m_renderTextureColorDatas.clear();
1063  m_renderMultitextureDatas.clear();
1064  m_renderObjects.clear();
1065  }
1066 
1068  // stride
1069  const uint32_t stride = sizeof(renderDataZ);
1070 
1071  // set pointer
1072  setVertexPointer(3, stride, &m_renderTextureDatasZ[0].vertex);
1073  setTexCoordPointer(0, stride, &m_renderTextureDatasZ[0].texel);
1074 
1075  // array index
1076  int32_t index = 0;
1077  // elements to render
1078  uint32_t elements = 0;
1079  // texture id
1080  uint32_t texture_id = 0;
1081 
1082  int32_t* currentIndex = &index;
1083  uint32_t* currentElements = &elements;
1084 
1085  enableAlphaTest();
1086  enableDepthTest();
1087  enableTextures(0);
1088  enableLighting();
1090 
1091  for(std::vector<RenderZObject>::iterator ir = m_renderTextureObjectsZ.begin(); ir != m_renderTextureObjectsZ.end(); ++ir) {
1092  RenderZObject& ro = (*ir);
1093  // if changes then we render all previously elements
1094  if (ro.texture_id != texture_id) {
1095  if (*currentElements > 0) {
1096  //render
1097  glDrawArrays(GL_QUADS, *currentIndex, *currentElements);
1098  *currentIndex += *currentElements;
1099  }
1100 
1101  if (ro.texture_id != 0) {
1102  bindTexture(0, ro.texture_id);
1103  texture_id = ro.texture_id;
1104  } else {
1105  disableTextures(0);
1106  texture_id = 0;
1107  }
1108 
1109  // set element to current size
1110  *currentElements = 4;
1111  } else {
1112  // else add the element
1113  *currentElements += 4;
1114  }
1115  }
1116 
1117  // render
1118  glDrawArrays(GL_QUADS, *currentIndex, *currentElements);
1119 
1120  //reset all states
1121  disableLighting();
1122  disableTextures(0);
1123  disableAlphaTest();
1124  disableDepthTest();
1125  enableColorArray();
1126 
1127  m_renderTextureDatasZ.clear();
1128  m_renderTextureObjectsZ.clear();
1129  }
1130 
1132  // stride
1133  const uint32_t stride = sizeof(renderDataZ);
1134 
1135  // set pointer
1136  setVertexPointer(3, stride, &m_renderZ_datas[0].vertex);
1137  setTexCoordPointer(0, stride, &m_renderZ_datas[0].texel);
1138 
1139  enableAlphaTest();
1140  enableDepthTest();
1141  enableTextures(0);
1142  enableLighting();
1144 
1145  std::vector<RenderZObjectTest>::iterator iter = m_renderZ_objects.begin();
1146  for ( ; iter != m_renderZ_objects.end(); ++iter) {
1147  bindTexture(iter->texture_id);
1148  glDrawArrays(GL_QUADS, iter->index, iter->elements);
1149  }
1150  m_renderZ_objects.clear();
1151 
1152  //reset all states
1153  disableLighting();
1154  disableTextures(0);
1155  disableAlphaTest();
1156  disableDepthTest();
1157  enableColorArray();
1158  }
1159 
1161  // stride
1162  const uint32_t stride = sizeof(renderDataColorZ);
1163 
1164  // set pointer
1165  setVertexPointer(3, stride, &m_renderTextureColorDatasZ[0].vertex);
1166  setTexCoordPointer(0, stride, &m_renderTextureColorDatasZ[0].texel);
1167  setColorPointer(stride, &m_renderTextureColorDatasZ[0].color);
1168 
1169  // array index
1170  int32_t index = 0;
1171  // elements to render
1172  uint32_t elements = 0;
1173  // texture id
1174  uint32_t texture_id = 0;
1175 
1176  int32_t* currentIndex = &index;
1177  uint32_t* currentElements = &elements;
1178 
1179  enableDepthTest();
1180  // use own value, other option would be to disable it
1181  setAlphaTest(0.008);
1182  enableTextures(0);
1183  enableLighting();
1184 
1185  for(std::vector<RenderZObject>::iterator ir = m_renderTextureColorObjectsZ.begin(); ir != m_renderTextureColorObjectsZ.end(); ++ir) {
1186  RenderZObject& ro = (*ir);
1187  // if changes then we render all previously elements
1188  if (ro.texture_id != texture_id) {
1189  if (*currentElements > 0) {
1190  //render
1191  glDrawArrays(GL_QUADS, *currentIndex, *currentElements);
1192  *currentIndex += *currentElements;
1193  }
1194 
1195  if (ro.texture_id != 0) {
1196  bindTexture(0, ro.texture_id);
1197  texture_id = ro.texture_id;
1198  } else {
1199  disableTextures(0);
1200  texture_id = 0;
1201  }
1202 
1203  // set element to current size
1204  *currentElements = 4;
1205  } else {
1206  // else add the element
1207  *currentElements += 4;
1208  }
1209  }
1210 
1211  // render
1212  glDrawArrays(GL_QUADS, *currentIndex, *currentElements);
1213 
1214  //reset all states
1215  disableLighting();
1216  disableTextures(0);
1218  disableAlphaTest();
1219  disableDepthTest();
1220 
1223  }
1224 
1226  //bools to indicate changes
1227  bool texture = false;
1228  bool render = false;
1229  bool mt = false;
1230 
1231  // stride
1232  const uint32_t stride = sizeof(renderData2TCZ);
1233 
1234  // set pointer
1235  setVertexPointer(3, stride, &m_renderMultitextureDatasZ[0].vertex);
1236  setTexCoordPointer(0, stride, &m_renderMultitextureDatasZ[0].texel);
1237  setTexCoordPointer(1, stride, &m_renderMultitextureDatasZ[0].texel2);
1238  setTexCoordPointer(2, stride, &m_renderMultitextureDatasZ[0].texel2);
1239  setTexCoordPointer(3, stride, &m_renderMultitextureDatasZ[0].texel2);
1240  setColorPointer(stride, &m_renderMultitextureDatasZ[0].color);
1241 
1242  // array index
1243  int32_t index = 0;
1244  // elements to render
1245  uint32_t elements = 0;
1246  // texture id
1247  uint32_t texture_id = 0;
1248  uint32_t texture_id2 = 0;
1249  // overlay type
1250  OverlayType overlay_type = OVERLAY_TYPE_NONE;
1251  // overlay color
1252  uint8_t color[4] = {0};
1253 
1254  int32_t* currentIndex = &index;
1255  uint32_t* currentElements = &elements;
1256 
1257  enableDepthTest();
1258  enableAlphaTest();
1259  enableTextures(0);
1260  enableLighting();
1261 
1262  for(std::vector<RenderObject>::iterator ir = m_renderMultitextureObjectsZ.begin(); ir != m_renderMultitextureObjectsZ.end(); ++ir) {
1263  RenderObject& ro = (*ir);
1264 
1265  // first we look for changes
1266  if (ro.texture_id != texture_id) {
1267  texture = true;
1268  render = true;
1269  }
1270  if (ro.overlay_type != overlay_type ||
1271  (ro.overlay_type != OVERLAY_TYPE_NONE && (memcmp(color, ro.rgba, sizeof(uint8_t) * 4) || ro.overlay_id != texture_id2))) {
1272  mt = true;
1273  render = true;
1274  }
1275 
1276  // if changes then we render all previously elements
1277  if (render) {
1278  if (*currentElements > 0) {
1279  //render
1280  glDrawArrays(GL_QUADS, *currentIndex, *currentElements);
1281  *currentIndex += *currentElements;
1282  }
1283  // multitexturing
1284  if(mt) {
1285  switch (ro.overlay_type) {
1286  case OVERLAY_TYPE_NONE:
1287  disableTextures(3);
1288  disableTextures(2);
1289  disableTextures(1);
1290  enableTextures(0);
1291 
1292  texture_id2 = 0;
1293  break;
1294  case OVERLAY_TYPE_COLOR:
1295  disableTextures(3);
1296  disableTextures(2);
1298  setEnvironmentalColor(1, ro.rgba);
1299  enableTextures(0);
1300 
1301  texture_id2 = m_maskOverlay;
1302  break;
1304  disableTextures(3);
1305  disableTextures(1);
1306  bindTexture(2, ro.overlay_id);
1307  setEnvironmentalColor(2, ro.rgba);
1308  enableTextures(0);
1309 
1310  texture_id2 = ro.overlay_id;
1311  break;
1313  disableTextures(2);
1314  disableTextures(1);
1315  bindTexture(3, ro.overlay_id);
1316  setEnvironmentalColor(3, ro.rgba);
1317  enableTextures(0);
1318 
1319  texture_id2 = ro.overlay_id;
1320  break;
1321  }
1322  memcpy(color, ro.rgba, sizeof(uint8_t) * 4);
1323  overlay_type = ro.overlay_type;
1324  mt = false;
1325  }
1326 
1327  // switch texturing
1328  if (texture) {
1329  if (ro.texture_id != 0) {
1330  bindTexture(0, ro.texture_id);
1331  texture_id = ro.texture_id;
1332  } else {
1333  disableTextures(0);
1334  texture_id = 0;
1335  }
1336  texture = false;
1337  }
1338 
1339  // set element to current size
1340  *currentElements = ro.size;
1341  render = false;
1342  } else {
1343  // else add the element
1344  *currentElements += ro.size;
1345  }
1346  }
1347  // render
1348  glDrawArrays(GL_QUADS, *currentIndex, *currentElements);
1349 
1350  //reset all states
1351  if (overlay_type != OVERLAY_TYPE_NONE) {
1352  disableTextures(3);
1353  disableTextures(2);
1354  disableTextures(1);
1355  }
1356  disableTextures(0);
1357  disableLighting();
1358  disableAlphaTest();
1359  disableDepthTest();
1360 
1363  }
1364 
1366  // z stuff
1367  if (!m_renderZ_objects.empty()) {
1368  renderWithZTest();
1369  }
1370  if (!m_renderTextureObjectsZ.empty()) {
1371  renderWithZ();
1372  }
1373  if (!m_renderMultitextureObjectsZ.empty()) {
1375  }
1376  if (!m_renderTextureColorObjectsZ.empty()) {
1378  }
1379 
1380  // objects without z
1381  if (!m_renderObjects.empty()) {
1382  renderWithoutZ();
1383  }
1384  }
1385 
1386  bool RenderBackendOpenGL::putPixel(int32_t x, int32_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
1387  if ((x < 0) || (x >= (int32_t)m_target->w) ||
1388  (y < 0) || (y >= (int32_t)m_target->h)) {
1389  return false;
1390  }
1391  renderDataP rd;
1392  rd.vertex[0] = static_cast<float>(x)+0.375;
1393  rd.vertex[1] = static_cast<float>(y)+0.375;
1394  rd.color[0] = r;
1395  rd.color[1] = g;
1396  rd.color[2] = b;
1397  rd.color[3] = a;
1398  m_renderPrimitiveDatas.push_back(rd);
1399 
1400  RenderObject ro(GL_POINTS, 1);
1401  m_renderObjects.push_back(ro);
1402 
1403  return true;
1404  }
1405 
1406  void RenderBackendOpenGL::drawLine(const Point& p1, const Point& p2, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
1407  renderDataP rd;
1408  rd.vertex[0] = static_cast<float>(p1.x)-0.375;
1409  rd.vertex[1] = static_cast<float>(p1.y)-0.375;
1410  rd.color[0] = r;
1411  rd.color[1] = g;
1412  rd.color[2] = b;
1413  rd.color[3] = a;
1414  m_renderPrimitiveDatas.push_back(rd);
1415 
1416  rd.vertex[0] = static_cast<float>(p2.x)-0.375;
1417  rd.vertex[1] = static_cast<float>(p2.y)-0.375;
1418  m_renderPrimitiveDatas.push_back(rd);
1419 
1420  RenderObject ro(GL_LINES, 2);
1421  m_renderObjects.push_back(ro);
1422  }
1423 
1424  void RenderBackendOpenGL::drawTriangle(const Point& p1, const Point& p2, const Point& p3, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
1425  renderDataP rd;
1426  rd.vertex[0] = static_cast<float>(p1.x);
1427  rd.vertex[1] = static_cast<float>(p1.y);
1428  rd.color[0] = r;
1429  rd.color[1] = g;
1430  rd.color[2] = b;
1431  rd.color[3] = a;
1432  m_renderPrimitiveDatas.push_back(rd);
1433 
1434  rd.vertex[0] = static_cast<float>(p2.x);
1435  rd.vertex[1] = static_cast<float>(p2.y);
1436  m_renderPrimitiveDatas.push_back(rd);
1437 
1438  rd.vertex[0] = static_cast<float>(p3.x);
1439  rd.vertex[1] = static_cast<float>(p3.y);
1440  m_renderPrimitiveDatas.push_back(rd);
1441 
1442  RenderObject ro(GL_TRIANGLES, 3);
1443  m_renderObjects.push_back(ro);
1444  }
1445 
1447  renderDataP rd;
1448  rd.vertex[0] = static_cast<float>(p.x);
1449  rd.vertex[1] = static_cast<float>(p.y);
1450  rd.color[0] = r;
1451  rd.color[1] = g;
1452  rd.color[2] = b;
1453  rd.color[3] = a;
1454  m_renderPrimitiveDatas.push_back(rd);
1455 
1456  rd.vertex[0] = static_cast<float>(p.x+w);
1457  m_renderPrimitiveDatas.push_back(rd);
1458 
1459  rd.vertex[1] = static_cast<float>(p.y+h);
1460  m_renderPrimitiveDatas.push_back(rd);
1461 
1462  rd.vertex[0] = static_cast<float>(p.x);
1463  m_renderPrimitiveDatas.push_back(rd);
1464 
1465  RenderObject ro(GL_LINE_LOOP, 4);
1466  m_renderObjects.push_back(ro);
1467  }
1468 
1470  renderDataP rd;
1471  rd.vertex[0] = static_cast<float>(p.x);
1472  rd.vertex[1] = static_cast<float>(p.y);
1473  rd.color[0] = r;
1474  rd.color[1] = g;
1475  rd.color[2] = b;
1476  rd.color[3] = a;
1477  m_renderPrimitiveDatas.push_back(rd);
1478 
1479  rd.vertex[1] = static_cast<float>(p.y+h);
1480  m_renderPrimitiveDatas.push_back(rd);
1481 
1482  rd.vertex[0] = static_cast<float>(p.x+w);
1483  m_renderPrimitiveDatas.push_back(rd);
1484 
1485  rd.vertex[1] = static_cast<float>(p.y);
1486  m_renderPrimitiveDatas.push_back(rd);
1487 
1488  RenderObject ro(GL_QUADS, 4);
1489  m_renderObjects.push_back(ro);
1490  }
1491 
1492  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) {
1493  renderDataP rd;
1494  rd.vertex[0] = static_cast<float>(p1.x);
1495  rd.vertex[1] = static_cast<float>(p1.y);
1496  rd.color[0] = r;
1497  rd.color[1] = g;
1498  rd.color[2] = b;
1499  rd.color[3] = a;
1500  m_renderPrimitiveDatas.push_back(rd);
1501 
1502  rd.vertex[0] = static_cast<float>(p2.x);
1503  rd.vertex[1] = static_cast<float>(p2.y);
1504  m_renderPrimitiveDatas.push_back(rd);
1505 
1506  rd.vertex[0] = static_cast<float>(p3.x);
1507  rd.vertex[1] = static_cast<float>(p3.y);
1508  m_renderPrimitiveDatas.push_back(rd);
1509 
1510  rd.vertex[0] = static_cast<float>(p4.x);
1511  rd.vertex[1] = static_cast<float>(p4.y);
1512  m_renderPrimitiveDatas.push_back(rd);
1513 
1514  RenderObject ro(GL_QUADS, 4);
1515  m_renderObjects.push_back(ro);
1516  }
1517 
1519  renderDataP rd;
1520  rd.vertex[0] = static_cast<float>(p.x-size);
1521  rd.vertex[1] = static_cast<float>(p.y+size);
1522  rd.color[0] = r;
1523  rd.color[1] = g;
1524  rd.color[2] = b;
1525  rd.color[3] = a;
1526  m_renderPrimitiveDatas.push_back(rd);
1527 
1528  rd.vertex[0] = static_cast<float>(p.x+size);
1529  m_renderPrimitiveDatas.push_back(rd);
1530 
1531  rd.vertex[1] = static_cast<float>(p.y-size);
1532  m_renderPrimitiveDatas.push_back(rd);
1533 
1534  rd.vertex[0] = static_cast<float>(p.x-size);
1535  m_renderPrimitiveDatas.push_back(rd);
1536 
1537  RenderObject ro(GL_LINE_LOOP, 4);
1538  m_renderObjects.push_back(ro);
1539  }
1540 
1541  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) {
1542  const float step = Mathf::twoPi()/subdivisions;
1543  renderDataP rd;
1544  RenderObject ro(GL_TRIANGLES, 3);
1545  for(float angle=0; angle<=Mathf::twoPi(); angle+=step){
1546  rd.vertex[0] = static_cast<float>(p.x);
1547  rd.vertex[1] = static_cast<float>(p.y);
1548  rd.color[0] = red;
1549  rd.color[1] = green;
1550  rd.color[2] = blue;
1551  rd.color[3] = intensity;
1552  m_renderPrimitiveDatas.push_back(rd);
1553 
1554  rd.vertex[0] = radius*Mathf::Cos(angle+step)*xstretch + p.x;
1555  rd.vertex[1] = radius*Mathf::Sin(angle+step)*ystretch + p.y;
1556  rd.color[0] = 0;
1557  rd.color[1] = 0;
1558  rd.color[2] = 0;
1559  rd.color[3] = 255;
1560  m_renderPrimitiveDatas.push_back(rd);
1561 
1562  rd.vertex[0] = radius*Mathf::Cos(angle)*xstretch + p.x;
1563  rd.vertex[1] = radius*Mathf::Sin(angle)*ystretch + p.y;
1564  m_renderPrimitiveDatas.push_back(rd);
1565 
1566  m_renderObjects.push_back(ro);
1567  }
1568  }
1569 
1570  void RenderBackendOpenGL::addImageToArray(uint32_t id, const Rect& rect, float const* st, uint8_t alpha, uint8_t const* rgba) {
1571  RenderObject ro(GL_QUADS, 4, id);
1572 
1573  // texture quad without alpha
1574  if (alpha == 255 && !rgba) {
1575  renderDataT rd;
1576  rd.vertex[0] = static_cast<float>(rect.x);
1577  rd.vertex[1] = static_cast<float>(rect.y);
1578  rd.texel[0] = st[0];
1579  rd.texel[1] = st[1];
1580  m_renderTextureDatas.push_back(rd);
1581 
1582  rd.vertex[0] = static_cast<float>(rect.x);
1583  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1584  rd.texel[1] = st[3];
1585  m_renderTextureDatas.push_back(rd);
1586 
1587  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1588  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1589  rd.texel[0] = st[2];
1590  m_renderTextureDatas.push_back(rd);
1591 
1592  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1593  rd.vertex[1] = static_cast<float>(rect.y);
1594  rd.texel[1] = st[1];
1595  m_renderTextureDatas.push_back(rd);
1596 
1597  ro.color = false;
1598  } else {
1599  if (rgba) {
1600  renderData2TC rd;
1601  rd.vertex[0] = static_cast<float>(rect.x);
1602  rd.vertex[1] = static_cast<float>(rect.y);
1603  rd.texel[0] = st[0];
1604  rd.texel[1] = st[1];
1605  rd.texel2[0] = 0.0;
1606  rd.texel2[1] = 0.0;
1607  rd.color[0] = 255;
1608  rd.color[1] = 255;
1609  rd.color[2] = 255;
1610  rd.color[3] = alpha;
1611  m_renderMultitextureDatas.push_back(rd);
1612 
1613  rd.vertex[0] = static_cast<float>(rect.x);
1614  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1615  rd.texel[1] = st[3];
1616  rd.texel2[1] = 1.0;
1617  m_renderMultitextureDatas.push_back(rd);
1618 
1619  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1620  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1621  rd.texel[0] = st[2];
1622  rd.texel2[0] = 1.0;
1623  m_renderMultitextureDatas.push_back(rd);
1624 
1625  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1626  rd.vertex[1] = static_cast<float>(rect.y);
1627  rd.texel[1] = st[1];
1628  rd.texel2[1] = 0.0;
1629  m_renderMultitextureDatas.push_back(rd);
1630 
1631  ro.color = true;
1633  ro.rgba[0] = rgba[0];
1634  ro.rgba[1] = rgba[1];
1635  ro.rgba[2] = rgba[2];
1636  ro.rgba[3] = rgba[3];
1637  // texture quad with alpha
1638  } else {
1639  renderDataTC rd;
1640  rd.vertex[0] = static_cast<float>(rect.x);
1641  rd.vertex[1] = static_cast<float>(rect.y);
1642  rd.texel[0] = st[0];
1643  rd.texel[1] = st[1];
1644  rd.color[0] = 255;
1645  rd.color[1] = 255;
1646  rd.color[2] = 255;
1647  rd.color[3] = alpha;
1648  m_renderTextureColorDatas.push_back(rd);
1649 
1650  rd.vertex[0] = static_cast<float>(rect.x);
1651  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1652  rd.texel[1] = st[3];
1653  m_renderTextureColorDatas.push_back(rd);
1654 
1655  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1656  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1657  rd.texel[0] = st[2];
1658  m_renderTextureColorDatas.push_back(rd);
1659 
1660  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1661  rd.vertex[1] = static_cast<float>(rect.y);
1662  rd.texel[1] = st[1];
1663  m_renderTextureColorDatas.push_back(rd);
1664 
1665  ro.color = true;
1666  }
1667  }
1668  m_renderObjects.push_back(ro);
1669  }
1670 
1671  void RenderBackendOpenGL::addImageToArray(const Rect& rect, uint32_t id1, float const* st1, uint32_t id2, float const* st2, uint8_t alpha, uint8_t const* rgba) {
1672  if (rgba) {
1673  renderData2TC rd;
1674  rd.vertex[0] = static_cast<float>(rect.x);
1675  rd.vertex[1] = static_cast<float>(rect.y);
1676  rd.texel[0] = st1[0];
1677  rd.texel[1] = st1[1];
1678  rd.texel2[0] = st2[0];
1679  rd.texel2[1] = st2[1];
1680  rd.color[0] = 255;
1681  rd.color[1] = 255;
1682  rd.color[2] = 255;
1683  rd.color[3] = alpha;
1684  m_renderMultitextureDatas.push_back(rd);
1685 
1686  rd.vertex[0] = static_cast<float>(rect.x);
1687  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1688  rd.texel[1] = st1[3];
1689  rd.texel2[1] = st2[3];
1690  m_renderMultitextureDatas.push_back(rd);
1691 
1692  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1693  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1694  rd.texel[0] = st1[2];
1695  rd.texel2[0] = st2[2];
1696  m_renderMultitextureDatas.push_back(rd);
1697 
1698  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1699  rd.vertex[1] = static_cast<float>(rect.y);
1700  rd.texel[1] = st1[1];
1701  rd.texel2[1] = st2[1];
1702  m_renderMultitextureDatas.push_back(rd);
1703 
1704  RenderObject ro(GL_QUADS, 4, id1, id2);
1706  ro.rgba[0] = rgba[0];
1707  ro.rgba[1] = rgba[1];
1708  ro.rgba[2] = rgba[2];
1709  ro.rgba[3] = rgba[3];
1710  m_renderObjects.push_back(ro);
1711  }
1712  }
1713 
1715  for (std::vector<RenderZObjectTest>::iterator it = m_renderZ_objects.begin(); it != m_renderZ_objects.end(); ++it) {
1716  if (it->texture_id == texture_id) {
1717  if (it->elements < it->max_size - 4) {
1718  return &(*it);
1719  }
1720  }
1721  }
1722  int32_t max_quads_per_texbatch = 1000;
1723  // nothing was found (or we were forced to make new batch), we need to create new one
1724  RenderZObjectTest obj;
1725  if (!m_renderZ_objects.empty()) {
1726  obj.index = m_renderZ_objects.back().index + m_renderZ_objects.back().max_size;
1727  } else {
1728  obj.index = 0;
1729  }
1730  obj.texture_id = texture_id;
1731  obj.elements = 0;
1732  obj.max_size = max_quads_per_texbatch * 4;
1733 
1734  m_renderZ_objects.push_back(obj);
1735  return &m_renderZ_objects.back();
1736  }
1737 
1738  void RenderBackendOpenGL::addImageToArrayZ(uint32_t id, const Rect& rect, float vertexZ, float const* st, uint8_t alpha, uint8_t const* rgba) {
1739  // texture quad without alpha and coloring
1740  if (alpha == 255 && !rgba) {
1741  // ToDo: Consider if this is better.
1742  /*RenderZObjectTest* renderObj = getRenderBufferObject(id);
1743  uint32_t offset = renderObj->index + renderObj->elements;
1744  renderObj->elements += 4;
1745 
1746  renderDataZ* rd = &m_renderZ_datas[offset];
1747  rd->vertex[0] = static_cast<float>(rect.x);
1748  rd->vertex[1] = static_cast<float>(rect.y);
1749  rd->vertex[2] = vertexZ;
1750  rd->texel[0] = st[0];
1751  rd->texel[1] = st[1];
1752 
1753  ++rd;
1754  rd->vertex[0] = static_cast<float>(rect.x);
1755  rd->vertex[1] = static_cast<float>(rect.y+rect.h);
1756  rd->vertex[2] = vertexZ;
1757  rd->texel[0] = st[0];
1758  rd->texel[1] = st[3];
1759 
1760  ++rd;
1761  rd->vertex[0] = static_cast<float>(rect.x+rect.w);
1762  rd->vertex[1] = static_cast<float>(rect.y+rect.h);
1763  rd->vertex[2] = vertexZ;
1764  rd->texel[0] = st[2];
1765  rd->texel[1] = st[3];
1766 
1767  ++rd;
1768  rd->vertex[0] = static_cast<float>(rect.x+rect.w);
1769  rd->vertex[1] = static_cast<float>(rect.y);
1770  rd->vertex[2] = vertexZ;
1771  rd->texel[0] = st[2];
1772  rd->texel[1] = st[1];*/
1773 
1774  renderDataZ rd;
1775  rd.vertex[0] = static_cast<float>(rect.x);
1776  rd.vertex[1] = static_cast<float>(rect.y);
1777  rd.vertex[2] = vertexZ;
1778  rd.texel[0] = st[0];
1779  rd.texel[1] = st[1];
1780  m_renderTextureDatasZ.push_back(rd);
1781 
1782  rd.vertex[0] = static_cast<float>(rect.x);
1783  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1784  rd.texel[1] = st[3];
1785  m_renderTextureDatasZ.push_back(rd);
1786 
1787  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1788  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1789  rd.texel[0] = st[2];
1790  m_renderTextureDatasZ.push_back(rd);
1791 
1792  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1793  rd.vertex[1] = static_cast<float>(rect.y);
1794  rd.texel[1] = st[1];
1795  m_renderTextureDatasZ.push_back(rd);
1796 
1797  RenderZObject ro;
1798  ro.texture_id = id;
1799  m_renderTextureObjectsZ.push_back(ro);
1800  } else {
1801  // multitexture with color, second texel is used for m_maskOverlay
1802  if (rgba) {
1803  renderData2TCZ rd;
1804  rd.vertex[0] = static_cast<float>(rect.x);
1805  rd.vertex[1] = static_cast<float>(rect.y);
1806  rd.vertex[2] = vertexZ;
1807  rd.texel[0] = st[0];
1808  rd.texel[1] = st[1];
1809  rd.texel2[0] = 0.0;
1810  rd.texel2[1] = 0.0;
1811  rd.color[0] = 255;
1812  rd.color[1] = 255;
1813  rd.color[2] = 255;
1814  rd.color[3] = alpha;
1815  m_renderMultitextureDatasZ.push_back(rd);
1816 
1817  rd.vertex[0] = static_cast<float>(rect.x);
1818  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1819  rd.texel[1] = st[3];
1820  rd.texel2[1] = 1.0;
1821  m_renderMultitextureDatasZ.push_back(rd);
1822 
1823  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1824  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1825  rd.texel[0] = st[2];
1826  rd.texel2[0] = 1.0;
1827  m_renderMultitextureDatasZ.push_back(rd);
1828 
1829  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1830  rd.vertex[1] = static_cast<float>(rect.y);
1831  rd.texel[1] = st[1];
1832  rd.texel2[1] = 0.0;
1833  m_renderMultitextureDatasZ.push_back(rd);
1834 
1835  RenderObject ro(GL_QUADS, 4, id);
1836  ro.color = true;
1838  ro.rgba[0] = rgba[0];
1839  ro.rgba[1] = rgba[1];
1840  ro.rgba[2] = rgba[2];
1841  ro.rgba[3] = rgba[3];
1842  m_renderMultitextureObjectsZ.push_back(ro);
1843  // texture with alpha
1844  } else {
1845  renderDataColorZ rd;
1846  rd.vertex[0] = static_cast<float>(rect.x);
1847  rd.vertex[1] = static_cast<float>(rect.y);
1848  rd.vertex[2] = vertexZ;
1849  rd.texel[0] = st[0];
1850  rd.texel[1] = st[1];
1851  rd.color[0] = 255;
1852  rd.color[1] = 255;
1853  rd.color[2] = 255;
1854  rd.color[3] = alpha;
1855  m_renderTextureColorDatasZ.push_back(rd);
1856 
1857  rd.vertex[0] = static_cast<float>(rect.x);
1858  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1859  rd.texel[1] = st[3];
1860  m_renderTextureColorDatasZ.push_back(rd);
1861 
1862  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1863  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1864  rd.texel[0] = st[2];
1865  m_renderTextureColorDatasZ.push_back(rd);
1866 
1867  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1868  rd.vertex[1] = static_cast<float>(rect.y);
1869  rd.texel[1] = st[1];
1870  m_renderTextureColorDatasZ.push_back(rd);
1871 
1872  RenderZObject ro;
1873  ro.texture_id = id;
1874  m_renderTextureColorObjectsZ.push_back(ro);
1875  }
1876  }
1877  }
1878 
1879  void RenderBackendOpenGL::addImageToArrayZ(const Rect& rect, float vertexZ, uint32_t id1, float const* st1, uint32_t id2, float const* st2, uint8_t alpha, uint8_t const* rgba) {
1880  if (rgba) {
1881  renderData2TCZ rd;
1882  rd.vertex[0] = static_cast<float>(rect.x);
1883  rd.vertex[1] = static_cast<float>(rect.y);
1884  rd.vertex[2] = vertexZ;
1885  rd.texel[0] = st1[0];
1886  rd.texel[1] = st1[1];
1887  rd.texel2[0] = st2[0];
1888  rd.texel2[1] = st2[1];
1889  rd.color[0] = 255;
1890  rd.color[1] = 255;
1891  rd.color[2] = 255;
1892  rd.color[3] = alpha;
1893  m_renderMultitextureDatasZ.push_back(rd);
1894 
1895  rd.vertex[0] = static_cast<float>(rect.x);
1896  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1897  rd.texel[1] = st1[3];
1898  rd.texel2[1] = st2[3];
1899  m_renderMultitextureDatasZ.push_back(rd);
1900 
1901  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1902  rd.vertex[1] = static_cast<float>(rect.y+rect.h);
1903  rd.texel[0] = st1[2];
1904  rd.texel2[0] = st2[2];
1905  m_renderMultitextureDatasZ.push_back(rd);
1906 
1907  rd.vertex[0] = static_cast<float>(rect.x+rect.w);
1908  rd.vertex[1] = static_cast<float>(rect.y);
1909  rd.texel[1] = st1[1];
1910  rd.texel2[1] = st2[1];
1911  m_renderMultitextureDatasZ.push_back(rd);
1912 
1913  //RenderObject ro(GL_QUADS, 4, id1);
1914  RenderObject ro(GL_QUADS, 4, id1, id2);
1916  ro.rgba[0] = rgba[0];
1917  ro.rgba[1] = rgba[1];
1918  ro.rgba[2] = rgba[2];
1919  ro.rgba[3] = rgba[3];
1920  m_renderMultitextureObjectsZ.push_back(ro);
1921  }
1922  }
1923 
1925  glActiveTexture(GL_TEXTURE1);
1926  glEnable(GL_TEXTURE_2D);
1927 
1928  if(m_maskOverlay == 0) {
1929  // Constant texture - can be constant across every tilesets
1930  glGenTextures(1, &m_maskOverlay);
1931 
1932  uint8_t dummydata[3] = {127, 127, 127};
1933  glBindTexture(GL_TEXTURE_2D, m_maskOverlay);
1934  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1935  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1936  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1937  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1938  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0,
1939  GL_RGB, GL_UNSIGNED_BYTE, dummydata);
1940  } else {
1941  glBindTexture(GL_TEXTURE_2D, m_maskOverlay);
1942  }
1943 
1945 
1946  // Texture Unit 1
1947  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1948  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
1949  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
1950 
1951  // Arg0
1952  glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
1953  glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
1954  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1955  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1956 
1957  // The alpha component is taken only from 0th tex unit which is
1958  // Arg0 in our case, therefore we doesn't need to set operands
1959  // and sources for the rest of arguments
1960 
1961  // Arg1
1962  glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
1963  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
1964 
1965  // Arg2
1966  // uses alpha part of environmental color as interpolation factor
1967  glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
1968  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
1969 
1970  glDisable(GL_TEXTURE_2D);
1971 
1972  // Texture Unit 2
1973  glClientActiveTexture(GL_TEXTURE2);
1974  glActiveTexture(GL_TEXTURE2);
1975  glEnable(GL_TEXTURE_2D);
1976 
1977  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1978  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
1979  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
1980 
1981  // Arg0
1982  glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
1983  glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE2);
1984  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1985  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1986 
1987  // The alpha component is taken only from 0th tex unit which is
1988  // Arg0 in our case, therefore we doesn't need to set operands
1989  // and sources for the rest of arguments
1990 
1991  // Arg1
1992  glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
1993  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
1994 
1995  // Arg2
1996  // uses alpha part of environmental color as interpolation factor
1997  glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
1998  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
1999 
2000  glDisable(GL_TEXTURE_2D);
2001 
2002  // Texture Unit 3
2003  glClientActiveTexture(GL_TEXTURE3);
2004  glActiveTexture(GL_TEXTURE3);
2005  glEnable(GL_TEXTURE_2D);
2006 
2007  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
2008  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
2009  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
2010 
2011  // Arg0
2012  glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
2013  glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE3);
2014  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
2015  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
2016 
2017  // The alpha component is taken only from 3th tex unit which is
2018  // Arg0 in our case, therefore we doesn't need to set operands
2019  // and sources for the rest of arguments
2020 
2021  // Arg1
2022  glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE3);
2023  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
2024 
2025  // Arg2
2026  // uses alpha part of environmental color as interpolation factor
2027  glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
2028  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
2029 
2030  // Return to normal sampling mode
2031  glDisable(GL_TEXTURE_2D);
2032  glActiveTexture(GL_TEXTURE0);
2033  m_state.active_tex = 0;
2034  glClientActiveTexture(GL_TEXTURE0);
2036 
2037  // For now it's unneecessary - Only needed if we intend to use the next texture unit in different case
2038  //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2039  }
2040 
2041  void RenderBackendOpenGL::captureScreen(const std::string& filename) {
2042  const uint32_t swidth = getWidth();
2043  const uint32_t sheight = getHeight();
2044 
2045  uint8_t *pixels;
2046  SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, sheight, 24,
2047  RMASK, GMASK, BMASK, NULLMASK);
2048 
2049  if (!surface) {
2050  return;
2051  }
2052 
2053  SDL_LockSurface(surface);
2054  pixels = new uint8_t[swidth * sheight * 3];
2055  glReadPixels(0, 0, swidth, sheight, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
2056  uint8_t *imagepixels = reinterpret_cast<uint8_t*>(surface->pixels);
2057  // Copy the "reversed_image" memory to the "image" memory
2058  for (int32_t y = (sheight - 1); y >= 0; --y) {
2059  uint8_t *rowbegin = pixels + y * swidth * 3;
2060  uint8_t *rowend = rowbegin + swidth * 3;
2061 
2062  std::copy(rowbegin, rowend, imagepixels);
2063 
2064  // Advance a row in the output surface.
2065  imagepixels += surface->pitch;
2066  }
2067 
2068  SDL_UnlockSurface(surface);
2069  Image::saveAsPng(filename, *surface);
2070 
2071  SDL_FreeSurface(surface);
2072  delete[] pixels;
2073  }
2074 
2075  void RenderBackendOpenGL::captureScreen(const std::string& filename, uint32_t width, uint32_t height) {
2076  const uint32_t swidth = getWidth();
2077  const uint32_t sheight = getHeight();
2078  const bool same_size = (width == swidth && height == sheight);
2079 
2080  if (width < 1 || height < 1) {
2081  return;
2082  }
2083 
2084  if (same_size) {
2085  captureScreen(filename);
2086  return;
2087  }
2088 
2089  uint8_t *pixels;
2090  // create source surface
2091  SDL_Surface* src = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, sheight, 32,
2092  RMASK, GMASK, BMASK, AMASK);
2093 
2094  if (!src) {
2095  return;
2096  }
2097 
2098  if (SDL_MUSTLOCK(src)) {
2099  SDL_LockSurface(src);
2100  }
2101  pixels = new uint8_t[swidth * sheight * 4];
2102  glReadPixels(0, 0, swidth, sheight, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
2103 
2104  uint8_t* imagepixels = reinterpret_cast<uint8_t*>(src->pixels);
2105  // Copy the "reversed_image" memory to the "image" memory
2106  for (int32_t y = (sheight - 1); y >= 0; --y) {
2107  uint8_t *rowbegin = pixels + y * swidth * 4;
2108  uint8_t *rowend = rowbegin + swidth * 4;
2109 
2110  std::copy(rowbegin, rowend, imagepixels);
2111 
2112  // Advance a row in the output surface.
2113  imagepixels += src->pitch;
2114  }
2115 
2116  // create destination surface
2117  SDL_Surface* dst = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,
2118  RMASK, GMASK, BMASK, AMASK);
2119 
2120  uint32_t* src_pointer = static_cast<uint32_t*>(src->pixels);
2121  uint32_t* src_help_pointer = src_pointer;
2122  uint32_t* dst_pointer = static_cast<uint32_t*>(dst->pixels);
2123 
2124  int32_t x, y, *sx_ca, *sy_ca;
2125  int32_t sx = static_cast<int32_t>(0xffff * src->w / dst->w);
2126  int32_t sy = static_cast<int32_t>(0xffff * src->h / dst->h);
2127  int32_t sx_c = 0;
2128  int32_t sy_c = 0;
2129 
2130  // Allocates memory and calculates row wide&height
2131  int32_t* sx_a = new int32_t[dst->w + 1];
2132  sx_ca = sx_a;
2133  for (x = 0; x <= dst->w; x++) {
2134  *sx_ca = sx_c;
2135  sx_ca++;
2136  sx_c &= 0xffff;
2137  sx_c += sx;
2138  }
2139 
2140  int32_t* sy_a = new int32_t[dst->h + 1];
2141  sy_ca = sy_a;
2142  for (y = 0; y <= dst->h; y++) {
2143  *sy_ca = sy_c;
2144  sy_ca++;
2145  sy_c &= 0xffff;
2146  sy_c += sy;
2147  }
2148  sy_ca = sy_a;
2149 
2150  // Transfers the image data
2151 
2152  if (SDL_MUSTLOCK(dst)) {
2153  SDL_LockSurface(dst);
2154  }
2155 
2156  for (y = 0; y < dst->h; y++) {
2157  src_pointer = src_help_pointer;
2158  sx_ca = sx_a;
2159  for (x = 0; x < dst->w; x++) {
2160  *dst_pointer = *src_pointer;
2161  sx_ca++;
2162  src_pointer += (*sx_ca >> 16);
2163  dst_pointer++;
2164  }
2165  sy_ca++;
2166  src_help_pointer = (uint32_t*)((uint8_t*)src_help_pointer + (*sy_ca >> 16) * src->pitch);
2167  }
2168 
2169  if (SDL_MUSTLOCK(dst)) {
2170  SDL_UnlockSurface(dst);
2171  }
2172  if (SDL_MUSTLOCK(src)) {
2173  SDL_UnlockSurface(src);
2174  }
2175 
2176  Image::saveAsPng(filename, *dst);
2177 
2178  // Free memory
2179  SDL_FreeSurface(src);
2180  SDL_FreeSurface(dst);
2181  delete[] sx_a;
2182  delete[] sy_a;
2183  delete[] pixels;
2184  }
2185 
2186  void RenderBackendOpenGL::setClipArea(const Rect& cliparea, bool clear) {
2187  glScissor(cliparea.x, getHeight() - cliparea.y - cliparea.h, cliparea.w, cliparea.h);
2188  if (clear) {
2189  if (m_isbackgroundcolor) {
2190  float red = float(m_backgroundcolor.r/255.0);
2191  float green = float(m_backgroundcolor.g/255.0);
2192  float blue = float(m_backgroundcolor.b/255.0);
2193  glClearColor(red, green, blue, 0.0);
2194  m_isbackgroundcolor = false;
2195  }
2196  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2197  }
2198  }
2199 
2201  // flush down what we batched for the old target
2203 
2204  m_img_target = img;
2205  m_target_discard = discard;
2206 
2207  // to render on something, we need to make sure its loaded already in gpu memory
2210 
2211  GLImage* glimage = static_cast<GLImage*>(m_img_target.get());
2212 
2213  GLuint targetid = glimage->getTexId();
2216 
2217  // quick & dirty hack for attaching compressed texture
2218  if(glimage->isCompressed()) {
2219  bindTexture(targetid);
2220  GLubyte* pixels = new GLubyte[w*h*4];
2221  // here we get decompressed pixels
2222  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
2223  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
2224  delete [] pixels;
2225  glimage->setCompressed(false);
2226  }
2227 
2228  // can we use fbo?
2229  if (GLEE_EXT_framebuffer_object && m_useframebuffer) {
2230  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo_id);
2231  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
2232  GL_TEXTURE_2D, targetid, 0);
2233 
2234  // currenty unused, is needed in case the static layers should be rendered with depth buffer (instead of sorting)
2235  // see LayerCache
2236  //glBindRenderbuffer(GL_RENDERBUFFER, m_depthbuffer_id);
2237  //glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h);
2238  //glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer_id);
2239  }
2240 
2241  glViewport(0, 0, w, h);
2242  glMatrixMode(GL_PROJECTION);
2243  glLoadIdentity();
2244  // invert top with bottom
2245  glOrtho(0, w, 0, h, -100, 100);
2246  glMatrixMode(GL_MODELVIEW);
2247  // because of inversion 2 lines above we need to also invert culling faces
2248  glCullFace(GL_FRONT);
2249 
2250  if (m_target_discard) {
2251  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2252  } else if (!m_target_discard && (!GLEE_EXT_framebuffer_object || !m_useframebuffer)) {
2253  // if we wanna just add something to render target, we need to first render previous contents
2254  addImageToArray(targetid, m_img_target->getArea(),
2255  static_cast<GLImage*>(m_img_target.get())->getTexCoords(), 255, 0);
2256  }
2257  }
2258 
2260  assert(m_target != m_screen);
2261 
2262  // flush down what we batched
2264 
2265  if (GLEE_EXT_framebuffer_object && m_useframebuffer) {
2266  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
2267  } else {
2268  bindTexture(0, static_cast<GLImage*>(m_img_target.get())->getTexId());
2269  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0,
2271  }
2272 
2273  m_target = m_screen;
2274  glViewport(0, 0, m_screen->w, m_screen->h);
2275  glMatrixMode(GL_PROJECTION);
2276  glLoadIdentity();
2277  glOrtho(0, m_screen->w, m_screen->h, 0, -100, 100);
2278  glMatrixMode(GL_MODELVIEW);
2279  glCullFace(GL_BACK);
2280  }
2281 
2282  void RenderBackendOpenGL::renderGuiGeometry(const std::vector<GuiVertex>& vertices, const std::vector<int>& indices, const DoublePoint& translation, ImagePtr texture) {
2283 
2284  glPushMatrix();
2285  glTranslatef(translation.x, translation.y, 0);
2286 
2287  glVertexPointer(2, GL_DOUBLE, sizeof(GuiVertex), &vertices[0].position);
2288  glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(GuiVertex), &vertices[0].color);
2289 
2290  GLuint texId = 0;
2291 
2292  GLImage* glImage = dynamic_cast<GLImage*>(texture.get());
2293  if(glImage) {
2294  glImage->forceLoadInternal();
2295  texId = glImage->getTexId();
2296  }
2297 
2298  if(texId == 0) {
2299  glDisable(GL_TEXTURE_2D);
2300  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2301  } else {
2302  glEnable(GL_TEXTURE_2D);
2303  glBindTexture(GL_TEXTURE_2D, texId);
2304  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2305  glTexCoordPointer(2, GL_DOUBLE, sizeof(GuiVertex), &vertices[0].texCoords);
2306  }
2307 
2308  glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, &indices[0]);
2309 
2310  glPopMatrix();
2311  }
2312 }
Abstract interface for all the renderbackends.
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.
std::vector< RenderZObjectTest > m_renderZ_objects
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("some text") << variable << "...
Definition: logger.h:82
SDL_PixelFormat m_rgba_format
T x
The X Coordinate.
Definition: rect.h:84
virtual void renderGuiGeometry(const std::vector< GuiVertex > &vertices, const std::vector< int > &indices, const DoublePoint &translation, ImagePtr texture)
Renders geometry required by gui.
uint32_t getHeight() const
void setCompressed(bool compressed)
Definition: glimage.h:80
uint32_t getSDLFlags() const
Returns the SDL flags used when testing this mode.
Definition: devicecaps.h:74
std::vector< renderDataP > m_renderPrimitiveDatas
virtual void renderVertexArrays()
Render the Vertex Arrays, only for primitives (points, lines,...)
std::vector< RenderObject > m_renderMultitextureObjectsZ
std::vector< renderDataColorZ > m_renderTextureColorDatasZ
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:231
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.
std::vector< renderData2TC > m_renderMultitextureDatas
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.
virtual void setClipArea(const Rect &cliparea, bool clear)
Sets given clip area into image.
GLuint getTexId() const
Definition: glimage.cpp:578
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.
RenderObject(GLenum m, uint16_t s, uint32_t t1=0, uint32_t t2=0)
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:176
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.
void setVertexPointer(GLint size, GLsizei stride, const GLvoid *ptr)
virtual void setLightingModel(uint32_t lighting)
Initializes the light.
virtual Image * createImage(IResourceLoader *loader=0)
uint32_t getHeight() const
Definition: image.cpp:160
unsigned char uint8_t
Definition: core.h:38
virtual void resetLighting()
Reset lighting with default values.
virtual void disableScissorTest()
Disables scissor test on the render backend.
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:95
static bool Equal(T _val1, T _val2)
Definition: fife_math.h:286
std::vector< renderDataT > m_renderTextureDatas
virtual void startFrame()
Called when a new frame starts.
static T Sin(T _val)
Definition: fife_math.h:266
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:79
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:151
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.
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
std::vector< renderDataZ > m_renderZ_datas
virtual void endFrame()
Called when a frame is finished and ready to be displayed.
virtual void forceLoadInternal()
Forces to load the image into internal memory of GPU.
Definition: glimage.cpp:510
std::vector< renderDataTC > m_renderTextureColorDatas
std::vector< renderData2TCZ > m_renderMultitextureDatasZ
TextureFiltering m_textureFilter
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).
std::vector< renderDataZ > m_renderTextureDatasZ
virtual void forceLoadInternal()=0
Forces to load the image into internal memory of GPU.
std::vector< RenderObject > m_renderObjects
Implements an Image using OpenGL.
Definition: glimage.h:53
RenderZObjectTest * getRenderBufferObject(GLuint texture_id)
RenderBackendOpenGL(const SDL_Color &colorkey)
void setEnvironmentalColor(uint32_t texUnit, const uint8_t *rgba)
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.
std::vector< RenderZObject > m_renderTextureColorObjectsZ
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 addImageToArrayZ(uint32_t id, const Rect &rect, float vertexZ, float const *st, uint8_t alpha, uint8_t const *rgba)
ScreenMode m_screenMode
virtual void attachRenderTarget(ImagePtr &img, bool discard)
Attaches given image as a new render surface.
RenderDataType
void deinit()
Performs cleanup actions.
unsigned int uint32_t
Definition: core.h:40
std::vector< RenderZObject > m_renderTextureObjectsZ
virtual void startFrame()
Called when a new frame starts.
T w
Width of the rectangle.
Definition: rect.h:90
virtual void enableScissorTest()
Enables scissor test on the render backend.
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.