30 #include "util/base/exception.h"
31 #include "util/log/logger.h"
32 #include "video/devicecaps.h"
35 #include "renderbackendopengle.h"
36 #include "SDL_image.h"
38 #define ALPHA_REF 0.3f
42 static Logger _log(LM_VIDEO);
44 class RenderBackendOpenGLe::RenderObject {
46 RenderObject(GLenum m, uint16_t s, uint32_t t=0):
73 const float RenderBackendOpenGLe::zfar = 100.0f;
74 const float RenderBackendOpenGLe::znear = -100.0f;
76 static const int max_quads_per_texbatch = 600;
77 static const int max_tex = 400;
78 static const int buffer_default_size = 4 * max_quads_per_texbatch * max_tex;
80 RenderBackendOpenGLe::RenderBackendOpenGLe(
const SDL_Color& colorkey)
81 : RenderBackend(colorkey), m_mask_overlays(0){
83 m_state.tex_enabled[0] =
false;
84 m_state.tex_enabled[1] =
false;
85 m_state.texture[0] = 0;
86 m_state.texture[1] = 0;
87 m_state.active_tex = 0;
89 m_state.lightmodel = 0;
90 m_state.light_enabled =
false;
92 m_state.sten_enabled =
false;
96 m_state.sten_func = 0;
98 m_state.env_color[0] = 0;
99 m_state.env_color[1] = 0;
100 m_state.env_color[2] = 0;
101 m_state.blend_src = GL_SRC_ALPHA;
102 m_state.blend_dst = GL_ONE_MINUS_SRC_ALPHA;
103 m_state.alpha_enabled =
true;
104 m_state.depth_enabled =
true;
105 m_state.scissor_test =
true;
108 RenderBackendOpenGLe::~RenderBackendOpenGLe() {
109 glDeleteTextures(1, &m_mask_overlays);
110 if(GLEE_EXT_framebuffer_object && m_useframebuffer) {
111 glDeleteFramebuffers(1, &m_fbo_id);
117 static std::string backend_name =
"OpenGLe";
123 Uint32 flags = SDL_INIT_VIDEO;
124 if (SDL_InitSubSystem(flags) < 0)
125 throw SDLException(SDL_GetError());
126 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
127 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
129 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
133 disableScissorTest();
134 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
140 SDL_Surface *img = IMG_Load(icon.c_str());
142 SDL_WM_SetIcon(img, 0);
143 SDL_FreeSurface(img);
148 SDL_WM_SetCaption(title.c_str(), 0);
152 uint16_t width = mode.getWidth();
153 uint16_t height = mode.getHeight();
154 uint16_t bitsPerPixel = mode.getBPP();
155 bool fs = mode.isFullScreen();
156 uint32_t flags = mode.getSDLFlags();
158 if (bitsPerPixel != 0) {
159 uint16_t bpp = SDL_VideoModeOK(width, height, bitsPerPixel, flags);
161 throw SDLException(
"Selected video mode not supported!");
166 SDL_FreeSurface(m_screen);
168 m_screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags);
170 throw SDLException(
"Unable to set video mode selected!");
174 FL_LOG(_log,
LMsg(
"RenderBackendOpenGLe")
175 <<
"Videomode " << width <<
"x" << height
176 <<
" at " << int32_t(bitsPerPixel) <<
" bpp");
178 m_rgba_format = *(m_screen->format);
179 m_rgba_format.Rmask = RMASK;
180 m_rgba_format.Gmask = GMASK;
181 m_rgba_format.Bmask = BMASK;
182 m_rgba_format.Amask = AMASK;
185 m_screenMode = ScreenMode(width,
191 throw SDLException(SDL_GetError());
194 glViewport(0, 0, width, height);
195 glMatrixMode(GL_PROJECTION);
197 glOrtho(0, width, height, 0, znear, zfar);
198 glMatrixMode(GL_MODELVIEW);
201 glEnable(GL_CULL_FACE);
205 glPixelStorei(GL_PACK_ALIGNMENT, 1);
206 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
208 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
213 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
214 glEnable(GL_ALPHA_TEST);
215 glAlphaFunc(GL_GREATER, ALPHA_REF);
216 glEnable(GL_DEPTH_TEST);
217 glDepthFunc(GL_LEQUAL);
219 glEnable(GL_SCISSOR_TEST);
221 glEnableClientState(GL_VERTEX_ARRAY);
223 prepareForOverlays();
228 if(GLEE_EXT_framebuffer_object && m_useframebuffer) {
229 glGenFramebuffers(1, &m_fbo_id);
232 m_renderZ_datas.resize(buffer_default_size);
240 SDL_GL_SwapBuffers();
244 Image* RenderBackendOpenGLe::createImage(IResourceLoader* loader) {
248 Image* RenderBackendOpenGLe::createImage(
const std::string& name, IResourceLoader* loader) {
249 return new GLeImage(name, loader);
252 Image* RenderBackendOpenGLe::createImage(SDL_Surface* surface) {
259 if (32 == surface->format->BitsPerPixel
260 && m_rgba_format.Rmask == surface->format->Rmask
261 && m_rgba_format.Gmask == surface->format->Gmask
262 && m_rgba_format.Bmask == surface->format->Bmask
263 && m_rgba_format.Amask == surface->format->Amask
264 && m_rgba_format.Rshift == surface->format->Rshift
265 && m_rgba_format.Gshift == surface->format->Gshift
266 && m_rgba_format.Bshift == surface->format->Bshift
267 && m_rgba_format.Ashift == surface->format->Ashift
268 && m_rgba_format.Rloss == surface->format->Rloss
269 && m_rgba_format.Gloss == surface->format->Gloss
270 && m_rgba_format.Bloss == surface->format->Bloss
271 && m_rgba_format.Aloss == surface->format->Aloss
272 && surface->flags & SDL_SRCALPHA ) {
277 uint8_t bpp = m_rgba_format.BitsPerPixel;
278 m_rgba_format.BitsPerPixel = 32;
279 SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA);
280 m_rgba_format.BitsPerPixel = bpp;
282 SDL_FreeSurface( surface );
286 Image* RenderBackendOpenGLe::createImage(
const std::string& name, SDL_Surface* surface) {
293 if (32 == surface->format->BitsPerPixel
294 && m_rgba_format.Rmask == surface->format->Rmask
295 && m_rgba_format.Gmask == surface->format->Gmask
296 && m_rgba_format.Bmask == surface->format->Bmask
297 && m_rgba_format.Amask == surface->format->Amask
298 && m_rgba_format.Rshift == surface->format->Rshift
299 && m_rgba_format.Gshift == surface->format->Gshift
300 && m_rgba_format.Bshift == surface->format->Bshift
301 && m_rgba_format.Ashift == surface->format->Ashift
302 && m_rgba_format.Rloss == surface->format->Rloss
303 && m_rgba_format.Gloss == surface->format->Gloss
304 && m_rgba_format.Bloss == surface->format->Bloss
305 && m_rgba_format.Aloss == surface->format->Aloss
306 && surface->flags & SDL_SRCALPHA ) {
311 uint8_t bpp = m_rgba_format.BitsPerPixel;
312 m_rgba_format.BitsPerPixel = 32;
313 SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA);
314 m_rgba_format.BitsPerPixel = bpp;
315 GLeImage* image =
new GLeImage(name, conv);
316 SDL_FreeSurface( surface );
320 Image* RenderBackendOpenGLe::createImage(
const uint8_t* data, uint32_t width, uint32_t height) {
321 return new GLeImage(data, width, height);
324 Image* RenderBackendOpenGLe::createImage(
const std::string& name,
const uint8_t* data, uint32_t width, uint32_t height) {
325 return new GLeImage(name, data, width, height);
329 if (m_state.lightmodel != lighting) {
330 if (m_state.lightmodel != 0) {
332 glDisable(GL_COLOR_MATERIAL);
333 }
else if (lighting != 0) {
334 m_state.lightmodel = lighting;
337 glColorMaterial(GL_FRONT, GL_DIFFUSE);
338 glEnable(GL_COLOR_MATERIAL);
340 m_state.lightmodel = lighting;
345 return m_state.lightmodel;
348 void RenderBackendOpenGLe::enableTextures(uint32_t texUnit) {
349 if(m_state.tex_enabled[texUnit] ==
false) {
350 if(m_state.active_tex != texUnit) {
351 m_state.active_tex = texUnit;
352 glActiveTexture(GL_TEXTURE0 + texUnit);
354 m_state.tex_enabled[texUnit] =
true;
356 glEnable(GL_TEXTURE_2D);
358 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
363 void RenderBackendOpenGLe::disableTextures(uint32_t texUnit)
365 if(m_state.tex_enabled[texUnit] ==
true) {
366 if(m_state.active_tex != texUnit) {
367 m_state.active_tex = texUnit;
368 glActiveTexture(GL_TEXTURE0 + texUnit);
370 m_state.tex_enabled[texUnit] =
false;
372 glDisable(GL_TEXTURE_2D);
374 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
379 void RenderBackendOpenGLe::bindTexture(uint32_t texUnit, GLuint texId) {
380 enableTextures(texUnit);
382 if(m_state.texture[texUnit] != texId) {
383 if(m_state.active_tex != texUnit) {
384 m_state.active_tex = texUnit;
385 glActiveTexture(GL_TEXTURE0 + texUnit);
387 m_state.texture[texUnit] = texId;
388 glBindTexture(GL_TEXTURE_2D, texId);
392 void RenderBackendOpenGLe::bindTexture(GLuint texId) {
393 if(m_state.texture[m_state.active_tex] != texId) {
394 m_state.texture[m_state.active_tex] = texId;
395 glBindTexture(GL_TEXTURE_2D, texId);
399 void RenderBackendOpenGLe::enableLighting() {
400 if (m_state.lightmodel != 0 && !m_state.light_enabled) {
401 glEnable(GL_LIGHTING);
402 m_state.light_enabled =
true;
406 void RenderBackendOpenGLe::disableLighting() {
407 if (m_state.lightmodel != 0 && m_state.light_enabled) {
408 glDisable(GL_LIGHTING);
409 m_state.light_enabled =
false;
414 if (m_state.lightmodel != 0) {
415 GLfloat lightDiffuse[] = {red, green, blue, 1.0f};
416 glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
421 m_state.light_enabled =
false;
424 void RenderBackendOpenGLe::enableStencilTest() {
425 if (!m_state.sten_enabled) {
426 glEnable(GL_STENCIL_TEST);
427 m_state.sten_enabled =
true;
431 void RenderBackendOpenGLe::disableStencilTest() {
432 if (m_state.sten_enabled) {
433 glDisable(GL_STENCIL_TEST);
434 m_state.sten_enabled =
false;
438 void RenderBackendOpenGLe::setStencilTest(uint8_t stencil_ref, GLenum stencil_op, GLenum stencil_func) {
440 if(m_state.sten_op != stencil_op) {
441 m_state.sten_op = stencil_op;
442 glStencilOp(GL_KEEP, GL_KEEP, m_state.sten_op);
445 if(m_state.sten_ref != stencil_ref || m_state.sten_func != stencil_func) {
446 m_state.sten_ref = stencil_ref;
447 m_state.sten_func = stencil_func;
448 glStencilFunc(m_state.sten_func, stencil_ref, 0xff);
453 if (buffer != m_state.sten_buf) {
454 m_state.sten_buf = buffer;
455 glClearStencil(buffer);
457 disableScissorTest();
458 glClear(GL_STENCIL_BUFFER_BIT);
462 void RenderBackendOpenGLe::enableAlphaTest() {
463 if (!m_state.alpha_enabled) {
464 glEnable(GL_ALPHA_TEST);
465 m_state.alpha_enabled =
true;
469 void RenderBackendOpenGLe::disableAlphaTest() {
470 if (m_state.alpha_enabled) {
471 glDisable(GL_ALPHA_TEST);
472 m_state.alpha_enabled =
false;
476 void RenderBackendOpenGLe::setAlphaTest(
float ref_alpha) {
478 glAlphaFunc(GL_GREATER, ref_alpha);
481 void RenderBackendOpenGLe::enableDepthTest() {
482 if (!m_state.depth_enabled) {
483 glEnable(GL_DEPTH_TEST);
484 m_state.depth_enabled =
true;
488 void RenderBackendOpenGLe::disableDepthTest() {
489 if (m_state.depth_enabled) {
490 glDisable(GL_DEPTH_TEST);
491 m_state.depth_enabled =
false;
495 void RenderBackendOpenGLe::setEnvironmentalColor(
const uint8_t* rgb) {
496 if (memcmp(m_state.env_color, rgb,
sizeof(uint8_t) * 3)) {
497 memcpy(m_state.env_color, rgb,
sizeof(uint8_t) * 3);
499 static_cast<float>(m_state.env_color[0]) / 255.0f,
500 static_cast<float>(m_state.env_color[1]) / 255.0f,
501 static_cast<float>(m_state.env_color[2]) / 255.0f, 0.0f};
502 glActiveTexture(GL_TEXTURE1);
503 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgbf);
504 glActiveTexture(GL_TEXTURE0);
508 void RenderBackendOpenGLe::enableScissorTest() {
509 if(m_state.scissor_test ==
false) {
510 m_state.scissor_test =
true;
511 glEnable(GL_SCISSOR_TEST);
515 void RenderBackendOpenGLe::disableScissorTest() {
516 if(m_state.scissor_test ==
true) {
517 m_state.scissor_test =
false;
518 glDisable(GL_SCISSOR_TEST);
527 case 0 : src_fact = GL_ZERO;
break;
528 case 1 : src_fact = GL_ONE;
break;
529 case 2 : src_fact = GL_DST_COLOR;
break;
530 case 3 : src_fact = GL_ONE_MINUS_DST_COLOR;
break;
531 case 4 : src_fact = GL_SRC_ALPHA;
break;
532 case 5 : src_fact = GL_ONE_MINUS_SRC_ALPHA;
break;
533 case 6 : src_fact = GL_DST_ALPHA;
break;
534 case 7 : src_fact = GL_ONE_MINUS_DST_ALPHA;
break;
536 default : src_fact = GL_DST_COLOR;
break;
540 case 0 : dst_fact = GL_ZERO;
break;
541 case 1 : dst_fact = GL_ONE;
break;
542 case 2 : dst_fact = GL_SRC_COLOR;
break;
543 case 3 : dst_fact = GL_ONE_MINUS_SRC_COLOR;
break;
544 case 4 : dst_fact = GL_SRC_ALPHA;
break;
545 case 5 : dst_fact = GL_ONE_MINUS_SRC_ALPHA;
break;
546 case 6 : dst_fact = GL_DST_ALPHA;
break;
547 case 7 : dst_fact = GL_ONE_MINUS_DST_ALPHA;
break;
549 default : dst_fact = GL_SRC_ALPHA;
break;
552 if (m_state.blend_src != src_fact || m_state.blend_dst != dst_fact) {
553 m_state.blend_src = src_fact;
554 m_state.blend_dst = dst_fact;
555 glBlendFunc(src_fact, dst_fact);
560 bool stentest, uint8_t stenref, GLConstants stenop, GLConstants stenfunc) {
563 uint32_t size = m_render_objects.size();
564 while (count != elements) {
566 RenderObject& r = m_render_objects.at(size-count);
572 r.stencil_test = stentest;
573 r.stencil_ref = stenref;
574 r.stencil_op = stenop;
575 r.stencil_func = stenfunc;
586 if(!m_renderZ_objects.empty() || !m_renderZ_objects_forced.empty()) {
594 if(!m_render_objects.empty()) {
599 void RenderBackendOpenGLe::renderWithZ() {
604 glDisableClientState(GL_COLOR_ARRAY);
607 static const uint32_t stride =
sizeof(RenderZData);
609 glVertexPointer(3, GL_FLOAT, stride, &m_renderZ_datas[0].vertex);
610 glTexCoordPointer(2, GL_FLOAT, stride, &m_renderZ_datas[0].texel);
612 std::vector<RenderZObject>::iterator iter = m_renderZ_objects.begin();
613 for ( ; iter != m_renderZ_objects.end(); ++iter) {
614 bindTexture(iter->texture_id);
615 glDrawArrays(GL_QUADS, iter->index, iter->elements);
617 m_renderZ_objects.clear();
621 if (!m_renderZ_objects_forced.empty()) {
622 static const uint32_t stride =
sizeof(RenderZData);
625 glVertexPointer(3, GL_FLOAT, stride, &m_renderZ_datas[0].vertex);
626 glTexCoordPointer(2, GL_FLOAT, stride, &m_renderZ_datas[0].texel);
627 setStencilTest(255, GL_REPLACE, GL_ALWAYS);
630 std::vector<RenderZObject>::iterator iter = m_renderZ_objects_forced.begin();
631 for ( ; iter != m_renderZ_objects_forced.end(); ++iter) {
632 bindTexture(iter->texture_id);
633 glDrawArrays(GL_QUADS, iter->index, iter->elements);
635 disableStencilTest();
637 m_renderZ_objects_forced.clear();
641 glEnableClientState(GL_COLOR_ARRAY);
644 if (!m_render_objects2T.empty()) {
645 static const uint32_t stride =
sizeof(RenderZData2T);
647 glActiveTexture(GL_TEXTURE1);
648 glEnable(GL_TEXTURE_2D);
649 glActiveTexture(GL_TEXTURE0);
651 glVertexPointer(3, GL_FLOAT, stride, &m_render_datas2T[0].vertex);
652 glColorPointer(4, GL_UNSIGNED_BYTE, stride, &m_render_datas2T[0].color);
654 glClientActiveTexture(GL_TEXTURE1);
655 glTexCoordPointer(2, GL_FLOAT, stride, &m_render_datas2T[0].texel2);
656 glClientActiveTexture(GL_TEXTURE0);
657 glTexCoordPointer(2, GL_FLOAT, stride, &m_render_datas2T[0].texel);
662 GLsizei elements = 0;
664 uint32_t texture_id = 0;
666 uint8_t rgb[3] = {0};
668 std::vector<RenderObject>::iterator iter = m_render_objects2T.begin();
669 for (; iter != m_render_objects2T.end(); ++iter) {
670 if (iter->texture_id != texture_id || memcmp(rgb, iter->rgb,
sizeof(uint8_t)*3)) {
672 glDrawArrays(GL_QUADS, index, elements);
676 setEnvironmentalColor(iter->rgb);
677 bindTexture(iter->texture_id);
678 texture_id = iter->texture_id;
679 elements = iter->size;;
680 memcpy(rgb, iter->rgb,
sizeof(uint8_t)*3);
682 elements += iter->size;
685 glDrawArrays(GL_QUADS, index, elements);
687 glActiveTexture(GL_TEXTURE1);
688 glDisable(GL_TEXTURE_2D);
689 glActiveTexture(GL_TEXTURE0);
691 m_render_objects2T.clear();
692 m_render_datas2T.clear();
699 if (!m_render_trans_objects.empty()) {
700 static const uint32_t stride =
sizeof(RenderZData2T);
702 glVertexPointer(3, GL_FLOAT, stride, &m_render_trans_datas[0].vertex);
703 glColorPointer(4, GL_UNSIGNED_BYTE, stride, &m_render_trans_datas[0].color);
704 glClientActiveTexture(GL_TEXTURE0);
705 glTexCoordPointer(2, GL_FLOAT, stride, &m_render_trans_datas[0].texel);
710 GLsizei elements = 0;
712 uint32_t texture_id = 0;
714 GLfloat rgb[3] = {0};
716 std::vector<RenderObject>::iterator iter = m_render_trans_objects.begin();
717 for( ; iter != m_render_trans_objects.end(); ++iter) {
718 if (iter->texture_id != texture_id) {
720 glDrawArrays(GL_QUADS, index, elements);
724 bindTexture(iter->texture_id);
725 texture_id = iter->texture_id;
726 elements = iter->size;;
728 elements += iter->size;
731 glDrawArrays(GL_QUADS, index, elements);
733 m_render_trans_datas.clear();
734 m_render_trans_objects.clear();
742 void RenderBackendOpenGLe::renderWithoutZ() {
745 bool texture =
false;
747 bool blending =
false;
748 bool stencil =
false;
750 static const uint32_t stride =
sizeof(RenderData);
752 glEnableClientState(GL_COLOR_ARRAY);
753 glVertexPointer(2, GL_FLOAT, stride, &m_render_datas[0].vertex);
754 glTexCoordPointer(2, GL_FLOAT, stride, &m_render_datas[0].texel);
755 glColorPointer(4, GL_UNSIGNED_BYTE, stride, &m_render_datas[0].color);
764 uint32_t elements = 0;
766 GLenum mode = GL_QUADS;
768 uint32_t texture_id = 0;
774 for(std::vector<RenderObject>::iterator iter = m_render_objects.begin(); iter != m_render_objects.end(); ++iter) {
776 if (iter->mode != mode) {
780 if (iter->texture_id != texture_id) {
784 if (m_state.lightmodel != 0) {
785 if (iter->src != src || iter->dst != dst) {
790 if (iter->stencil_test != m_state.sten_enabled) {
794 if (iter->stencil_ref != m_state.sten_ref ||
795 iter->stencil_op != m_state.sten_op ||
796 iter->stencil_func != m_state.sten_func) {
804 elements += iter->size;
809 glDrawArrays(mode, index, elements);
813 elements = iter->size;
822 if (iter->texture_id != 0) {
824 bindTexture(iter->texture_id);
825 texture_id = iter->texture_id;
833 if (m_state.lightmodel != 0) {
843 if (iter->stencil_test) {
844 setStencilTest(iter->stencil_ref, iter->stencil_op, iter->stencil_func);
847 disableStencilTest();
858 glDrawArrays(mode, index, elements);
861 disableStencilTest();
865 glDisableClientState(GL_COLOR_ARRAY);
867 m_render_objects.clear();
868 m_render_datas.clear();
872 if ((x < 0) || (x >= (int32_t)m_target->w) ||
873 (y < 0) || (y >= (int32_t)m_target->h)) {
877 rd.vertex[0] =
static_cast<float>(x);
878 rd.vertex[1] =
static_cast<float>(y);
883 m_render_datas.push_back(rd);
885 RenderObject ro(GL_POINTS, 1);
886 m_render_objects.push_back(ro);
893 rd.vertex[0] =
static_cast<float>(p1.x);
894 rd.vertex[1] =
static_cast<float>(p1.y);
899 m_render_datas.push_back(rd);
901 rd.vertex[0] =
static_cast<float>(p2.x);
902 rd.vertex[1] =
static_cast<float>(p2.y);
903 m_render_datas.push_back(rd);
905 RenderObject ro(GL_LINES, 2);
906 m_render_objects.push_back(ro);
911 rd.vertex[0] =
static_cast<float>(p1.x);
912 rd.vertex[1] =
static_cast<float>(p1.y);
917 m_render_datas.push_back(rd);
919 rd.vertex[0] =
static_cast<float>(p2.x);
920 rd.vertex[1] =
static_cast<float>(p2.y);
921 m_render_datas.push_back(rd);
923 rd.vertex[0] =
static_cast<float>(p3.x);
924 rd.vertex[1] =
static_cast<float>(p3.y);
925 m_render_datas.push_back(rd);
927 RenderObject ro(GL_TRIANGLES, 3);
928 m_render_objects.push_back(ro);
933 rd.vertex[0] =
static_cast<float>(p.x);
934 rd.vertex[1] =
static_cast<float>(p.y);
939 m_render_datas.push_back(rd);
940 rd.vertex[0] =
static_cast<float>(p.x+w);
942 m_render_datas.push_back(rd);
943 rd.vertex[1] =
static_cast<float>(p.y+h);
945 m_render_datas.push_back(rd);
946 rd.vertex[0] =
static_cast<float>(p.x);
947 m_render_datas.push_back(rd);
949 RenderObject ro(GL_LINE_LOOP, 4);
950 m_render_objects.push_back(ro);
955 rd.vertex[0] =
static_cast<float>(p.x);
956 rd.vertex[1] =
static_cast<float>(p.y);
961 m_render_datas.push_back(rd);
963 rd.vertex[1] =
static_cast<float>(p.y+h);
964 m_render_datas.push_back(rd);
966 rd.vertex[0] =
static_cast<float>(p.x+w);
967 m_render_datas.push_back(rd);
969 rd.vertex[1] =
static_cast<float>(p.y);
970 m_render_datas.push_back(rd);
972 RenderObject ro(GL_QUADS, 4);
973 m_render_objects.push_back(ro);
978 rd.vertex[0] =
static_cast<float>(p1.x);
979 rd.vertex[1] =
static_cast<float>(p1.y);
984 m_render_datas.push_back(rd);
986 rd.vertex[0] =
static_cast<float>(p2.x);
987 rd.vertex[1] =
static_cast<float>(p2.y);
988 m_render_datas.push_back(rd);
990 rd.vertex[0] =
static_cast<float>(p3.x);
991 rd.vertex[1] =
static_cast<float>(p3.y);
992 m_render_datas.push_back(rd);
994 rd.vertex[0] =
static_cast<float>(p4.x);
995 rd.vertex[1] =
static_cast<float>(p4.y);
996 m_render_datas.push_back(rd);
998 RenderObject ro(GL_QUADS, 4);
999 m_render_objects.push_back(ro);
1004 rd.vertex[0] =
static_cast<float>(p.x-size);
1005 rd.vertex[1] =
static_cast<float>(p.y+size);
1010 m_render_datas.push_back(rd);
1012 rd.vertex[0] =
static_cast<float>(p.x+size);
1013 m_render_datas.push_back(rd);
1015 rd.vertex[1] =
static_cast<float>(p.y-size);
1016 m_render_datas.push_back(rd);
1018 rd.vertex[0] =
static_cast<float>(p.x-size);
1019 m_render_datas.push_back(rd);
1021 RenderObject ro(GL_LINE_LOOP, 4);
1022 m_render_objects.push_back(ro);
1026 float xstretch,
float ystretch, uint8_t red, uint8_t green, uint8_t blue) {
1027 const float step = Mathf::twoPi()/subdivisions;
1029 for(
float angle=0; angle<=Mathf::twoPi(); angle+=step){
1030 rd.vertex[0] =
static_cast<float>(p.x);
1031 rd.vertex[1] =
static_cast<float>(p.y);
1033 rd.color[1] = green;
1035 rd.color[3] = intensity;
1036 m_render_datas.push_back(rd);
1038 rd.vertex[0] = radius*Mathf::Cos(angle+step)*xstretch + p.x;
1039 rd.vertex[1] = radius*Mathf::Sin(angle+step)*ystretch + p.y;
1044 m_render_datas.push_back(rd);
1046 rd.vertex[0] = radius*Mathf::Cos(angle)*xstretch + p.x;
1047 rd.vertex[1] = radius*Mathf::Sin(angle)*ystretch + p.y;
1048 m_render_datas.push_back(rd);
1050 RenderObject ro(GL_TRIANGLES, 3);
1051 m_render_objects.push_back(ro);
1057 rd.vertex[0] =
static_cast<float>(rect.
x);
1058 rd.vertex[1] =
static_cast<float>(rect.
y);
1059 rd.texel[0] = st[0];
1060 rd.texel[1] = st[1];
1064 rd.color[3] = alpha;
1065 m_render_datas.push_back(rd);
1067 rd.vertex[0] =
static_cast<float>(rect.
x);
1068 rd.vertex[1] =
static_cast<float>(rect.
y+rect.
h);
1069 rd.texel[1] = st[3];
1070 m_render_datas.push_back(rd);
1072 rd.vertex[0] =
static_cast<float>(rect.
x+rect.
w);
1073 rd.vertex[1] =
static_cast<float>(rect.
y+rect.
h);
1074 rd.texel[0] = st[2];
1075 m_render_datas.push_back(rd);
1077 rd.vertex[0] =
static_cast<float>(rect.
x+rect.
w);
1078 rd.vertex[1] =
static_cast<float>(rect.
y);
1079 rd.texel[1] = st[1];
1080 m_render_datas.push_back(rd);
1082 RenderObject ro(GL_QUADS, 4,
id);
1083 m_render_objects.push_back(ro);
1086 RenderBackendOpenGLe::RenderZObject* RenderBackendOpenGLe::getRenderBufferObject(GLuint texture_id,
bool forceNewBatch) {
1087 if (!forceNewBatch) {
1088 for (std::vector<RenderZObject>::iterator it = m_renderZ_objects.begin(); it != m_renderZ_objects.end(); ++it) {
1089 if (it->texture_id == texture_id) {
1090 if (it->elements < it->max_size - 4) {
1096 static int last_forced = 0;
1100 if (!m_renderZ_objects.empty()) {
1101 obj.index = m_renderZ_objects.back().index + m_renderZ_objects.back().max_size;
1102 obj.index += last_forced * 4;
1106 obj.texture_id = texture_id;
1108 obj.max_size = forceNewBatch ? 4 : max_quads_per_texbatch * 4;
1110 if (!forceNewBatch) {
1112 m_renderZ_objects.push_back(obj);
1113 return &m_renderZ_objects.back();
1116 m_renderZ_objects_forced.push_back(obj);
1117 return &m_renderZ_objects_forced.back();
1121 void RenderBackendOpenGLe::addImageToArrayZ(uint32_t
id,
const Rect& rect,
float vertexZ,
float const* st, uint8_t alpha,
bool forceNewBatch, uint8_t
const* rgb) {
1125 RenderZObject* renderObj = getRenderBufferObject(
id, forceNewBatch);
1126 uint32_t offset = renderObj->index + renderObj->elements;
1127 renderObj->elements += 4;
1130 rd = &m_renderZ_datas[offset];
1131 rd->vertex[0] =
static_cast<float>(rect.x);
1132 rd->vertex[1] =
static_cast<float>(rect.y);
1133 rd->vertex[2] = vertexZ;
1134 rd->texel[0] = st[0];
1135 rd->texel[1] = st[1];
1138 rd->vertex[0] =
static_cast<float>(rect.x);
1139 rd->vertex[1] =
static_cast<float>(rect.y+rect.h);
1140 rd->vertex[2] = vertexZ;
1141 rd->texel[0] = st[0];
1142 rd->texel[1] = st[3];
1145 rd->vertex[0] =
static_cast<float>(rect.x+rect.w);
1146 rd->vertex[1] =
static_cast<float>(rect.y+rect.h);
1147 rd->vertex[2] = vertexZ;
1148 rd->texel[0] = st[2];
1149 rd->texel[1] = st[3];
1152 rd->vertex[0] =
static_cast<float>(rect.x+rect.w);
1153 rd->vertex[1] =
static_cast<float>(rect.y);
1154 rd->vertex[2] = vertexZ;
1155 rd->texel[0] = st[2];
1156 rd->texel[1] = st[1];
1160 rd.vertex[0] =
static_cast<float>(rect.x);
1161 rd.vertex[1] =
static_cast<float>(rect.y);
1162 rd.vertex[2] = vertexZ;
1163 rd.texel[0] = st[0];
1164 rd.texel[1] = st[1];
1171 m_render_datas2T.push_back(rd);
1173 rd.vertex[0] =
static_cast<float>(rect.x);
1174 rd.vertex[1] =
static_cast<float>(rect.y+rect.h);
1175 rd.texel[1] = st[3];
1177 m_render_datas2T.push_back(rd);
1179 rd.vertex[0] =
static_cast<float>(rect.x+rect.w);
1180 rd.vertex[1] =
static_cast<float>(rect.y+rect.h);
1181 rd.texel[0] = st[2];
1183 m_render_datas2T.push_back(rd);
1185 rd.vertex[0] =
static_cast<float>(rect.x+rect.w);
1186 rd.vertex[1] =
static_cast<float>(rect.y);
1187 rd.texel[1] = st[1];
1189 m_render_datas2T.push_back(rd);
1191 RenderObject ro(GL_QUADS, 4,
id);
1195 m_render_objects2T.push_back(ro);
1199 rd.vertex[0] =
static_cast<float>(rect.x);
1200 rd.vertex[1] =
static_cast<float>(rect.y);
1201 rd.vertex[2] = vertexZ;
1202 rd.texel[0] = st[0];
1203 rd.texel[1] = st[1];
1207 rd.color[3] = alpha;
1208 m_render_trans_datas.push_back(rd);
1210 rd.vertex[0] =
static_cast<float>(rect.x);
1211 rd.vertex[1] =
static_cast<float>(rect.y+rect.h);
1212 rd.texel[1] = st[3];
1213 m_render_trans_datas.push_back(rd);
1215 rd.vertex[0] =
static_cast<float>(rect.x+rect.w);
1216 rd.vertex[1] =
static_cast<float>(rect.y+rect.h);
1217 rd.texel[0] = st[2];
1218 m_render_trans_datas.push_back(rd);
1220 rd.vertex[0] =
static_cast<float>(rect.x+rect.w);
1221 rd.vertex[1] =
static_cast<float>(rect.y);
1222 rd.texel[1] = st[1];
1223 m_render_trans_datas.push_back(rd);
1225 RenderObject ro(GL_QUADS, 4,
id);
1227 RenderObject ro(GL_QUADS, 4,
id);
1232 m_render_trans_objects.push_back(ro);
1237 void RenderBackendOpenGLe::prepareForOverlays() {
1238 glActiveTexture(GL_TEXTURE1);
1239 glEnable(GL_TEXTURE_2D);
1241 if(m_mask_overlays == 0) {
1243 glGenTextures(1, &m_mask_overlays);
1245 uint8_t dummydata[3] = {127, 127, 127};
1246 glBindTexture(GL_TEXTURE_2D, m_mask_overlays);
1247 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1248 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1249 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1250 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1251 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0,
1252 GL_RGB, GL_UNSIGNED_BYTE, dummydata);
1254 glBindTexture(GL_TEXTURE_2D, m_mask_overlays);
1257 m_state.texture[1] = m_mask_overlays;
1259 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1260 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
1261 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
1264 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
1265 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
1266 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1267 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1274 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
1275 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
1278 glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE1);
1279 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
1282 glActiveTexture(GL_TEXTURE1);
1283 glDisable(GL_TEXTURE_2D);
1284 glActiveTexture(GL_TEXTURE0);
1291 const uint32_t swidth = getWidth();
1292 const uint32_t sheight = getHeight();
1295 SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, sheight, 24,
1296 RMASK, GMASK, BMASK, NULLMASK);
1302 SDL_LockSurface(surface);
1303 pixels =
new uint8_t[swidth * sheight * 3];
1304 glReadPixels(0, 0, swidth, sheight, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
1305 uint8_t *imagepixels =
reinterpret_cast<uint8_t*
>(surface->pixels);
1307 for (int32_t y = (sheight - 1); y >= 0; --y) {
1308 uint8_t *rowbegin = pixels + y * swidth * 3;
1309 uint8_t *rowend = rowbegin + swidth * 3;
1311 std::copy(rowbegin, rowend, imagepixels);
1314 imagepixels += surface->pitch;
1317 SDL_UnlockSurface(surface);
1320 SDL_FreeSurface(surface);
1325 const uint32_t swidth = getWidth();
1326 const uint32_t sheight = getHeight();
1327 const bool same_size = (width == swidth && height == sheight);
1329 if (width < 1 || height < 1) {
1340 SDL_Surface* src = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, sheight, 32,
1341 RMASK, GMASK, BMASK, AMASK);
1347 if (SDL_MUSTLOCK(src)) {
1348 SDL_LockSurface(src);
1350 pixels =
new uint8_t[swidth * sheight * 4];
1351 glReadPixels(0, 0, swidth, sheight, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
1353 uint8_t* imagepixels =
reinterpret_cast<uint8_t*
>(src->pixels);
1355 for (int32_t y = (sheight - 1); y >= 0; --y) {
1356 uint8_t *rowbegin = pixels + y * swidth * 4;
1357 uint8_t *rowend = rowbegin + swidth * 4;
1359 std::copy(rowbegin, rowend, imagepixels);
1362 imagepixels += src->pitch;
1366 SDL_Surface* dst = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,
1367 RMASK, GMASK, BMASK, AMASK);
1369 uint32_t* src_pointer =
static_cast<uint32_t*
>(src->pixels);
1370 uint32_t* src_help_pointer = src_pointer;
1371 uint32_t* dst_pointer =
static_cast<uint32_t*
>(dst->pixels);
1373 int32_t x, y, *sx_ca, *sy_ca;
1374 int32_t sx =
static_cast<int32_t
>(0xffff * src->w / dst->w);
1375 int32_t sy =
static_cast<int32_t
>(0xffff * src->h / dst->h);
1380 int32_t* sx_a =
new int32_t[dst->w + 1];
1382 for (x = 0; x <= dst->w; x++) {
1389 int32_t* sy_a =
new int32_t[dst->h + 1];
1391 for (y = 0; y <= dst->h; y++) {
1401 if (SDL_MUSTLOCK(dst)) {
1402 SDL_LockSurface(dst);
1405 for (y = 0; y < dst->h; y++) {
1406 src_pointer = src_help_pointer;
1408 for (x = 0; x < dst->w; x++) {
1409 *dst_pointer = *src_pointer;
1411 src_pointer += (*sx_ca >> 16);
1415 src_help_pointer = (uint32_t*)((uint8_t*)src_help_pointer + (*sy_ca >> 16) * src->pitch);
1418 if (SDL_MUSTLOCK(dst)) {
1419 SDL_UnlockSurface(dst);
1421 if (SDL_MUSTLOCK(src)) {
1422 SDL_UnlockSurface(src);
1428 SDL_FreeSurface(src);
1429 SDL_FreeSurface(dst);
1436 glScissor(cliparea.
x, getHeight() - cliparea.
y - cliparea.
h, cliparea.
w, cliparea.
h);
1438 if (m_isbackgroundcolor) {
1439 float red = float(m_backgroundcolor.r/255.0);
1440 float green = float(m_backgroundcolor.g/255.0);
1441 float blue = float(m_backgroundcolor.b/255.0);
1442 glClearColor(red, green, blue, 0.0);
1443 m_isbackgroundcolor =
false;
1445 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1451 m_target_discard = discard;
1455 m_target = m_img_target->getSurface();
1459 GLuint targetid = glimage->getTexId();
1460 uint32_t w = m_img_target->getWidth();
1461 uint32_t h = m_img_target->getHeight();
1464 if(glimage->isCompressed()) {
1465 bindTexture(targetid);
1466 GLubyte* pixels =
new GLubyte[w*h*4];
1468 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1469 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1471 glimage->setCompressed(
false);
1475 if (GLEE_EXT_framebuffer_object && m_useframebuffer) {
1476 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo_id);
1477 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
1478 GL_TEXTURE_2D, targetid, 0);
1481 glViewport(0, 0, w, h);
1482 glMatrixMode(GL_PROJECTION);
1485 glOrtho(0, w, 0, h, -1, 1);
1486 glMatrixMode(GL_MODELVIEW);
1488 glCullFace(GL_FRONT);
1490 if (m_target_discard) {
1491 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1492 }
else if (!m_target_discard && (!GLEE_EXT_framebuffer_object || !m_useframebuffer)) {
1495 static_cast<GLeImage*
>(m_img_target.
get())->getTexCoords(), 255, 0);
1502 assert(m_target != m_screen);
1507 if (GLEE_EXT_framebuffer_object && m_useframebuffer) {
1508 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1510 bindTexture(0, static_cast<GLeImage*>(m_img_target.
get())->getTexId());
1511 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0,
1512 m_img_target->getWidth(), m_img_target->getHeight(), 0);
1513 glClear(GL_DEPTH_BUFFER_BIT);
1516 m_target = m_screen;
1517 glViewport(0, 0, m_screen->w, m_screen->h);
1518 glMatrixMode(GL_PROJECTION);
1520 glOrtho(0, m_screen->w, m_screen->h, 0, znear, zfar);
1521 glMatrixMode(GL_MODELVIEW);
1522 glCullFace(GL_BACK);
virtual void detachRenderTarget()
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)
virtual void attachRenderTarget(ImagePtr &img, bool discard)
virtual void init(const std::string &driver)
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)
virtual void changeBlending(int32_t scr, int32_t dst)
virtual void createMainScreen(const ScreenMode &mode, const std::string &title, const std::string &icon)
static void saveAsPng(const std::string &filename, const SDL_Surface &surface)
virtual void drawLine(const Point &p1, const Point &p2, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
virtual void renderVertexArrays()
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)
virtual void setLighting(float red, float green, float blue)
virtual const std::string & getName() const
virtual void startFrame()
virtual void resetLighting()
virtual void startFrame()
virtual void changeRenderInfos(uint16_t elements, int32_t src, int32_t dst, bool light, bool stentest, uint8_t stenref, GLConstants stenop, GLConstants stenfunc)
virtual void setScreenMode(const ScreenMode &mode)
virtual bool putPixel(int32_t x, int32_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
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)
virtual void setLightingModel(uint32_t lighting)
virtual void addImageToArray(uint32_t id, const Rect &rec, float const *st, uint8_t alpha, uint8_t const *rgb)
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)
virtual void captureScreen(const std::string &filename)
virtual void drawVertex(const Point &p, const uint8_t size, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
virtual void clearBackBuffer()
virtual void forceLoadInternal()=0
virtual uint32_t getLightingModel() const
virtual void resetStencilBuffer(uint8_t buffer)
virtual void setClipArea(const Rect &cliparea, bool clear)