00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <SDL.h>
00028
00029
00030 #include "util/base/exception.h"
00031 #include "util/log/logger.h"
00032 #include "video/devicecaps.h"
00033
00034 #include "gleimage.h"
00035 #include "renderbackendopengle.h"
00036 #include "SDL_image.h"
00037
00038 #define ALPHA_REF 0.3f
00039
00040
00041 namespace FIFE {
00042 static Logger _log(LM_VIDEO);
00043
00044 class RenderBackendOpenGLe::RenderObject {
00045 public:
00046 RenderObject(GLenum m, uint16_t s, uint32_t t=0):
00047 mode(m),
00048 size(s),
00049 texture_id(t),
00050 src(4),
00051 dst(5),
00052 light(true),
00053 stencil_test(false),
00054 stencil_ref(0),
00055 stencil_op(0),
00056 stencil_func(0)
00057 {}
00058
00059 public:
00060 GLenum mode;
00061 uint16_t size;
00062 uint32_t texture_id;
00063 int32_t src;
00064 int32_t dst;
00065 bool light;
00066 bool stencil_test;
00067 uint8_t stencil_ref;
00068 GLenum stencil_op;
00069 GLenum stencil_func;
00070 uint8_t rgb[3];
00071 };
00072
00073 const float RenderBackendOpenGLe::zfar = 100.0f;
00074 const float RenderBackendOpenGLe::znear = -100.0f;
00075
00076 static const int max_quads_per_texbatch = 600;
00077 static const int max_tex = 400;
00078 static const int buffer_default_size = 4 * max_quads_per_texbatch * max_tex;
00079
00080 RenderBackendOpenGLe::RenderBackendOpenGLe(const SDL_Color& colorkey)
00081 : RenderBackend(colorkey), m_mask_overlays(0){
00082
00083 m_state.tex_enabled[0] = false;
00084 m_state.tex_enabled[1] = false;
00085 m_state.texture[0] = 0;
00086 m_state.texture[1] = 0;
00087 m_state.active_tex = 0;
00088
00089 m_state.lightmodel = 0;
00090 m_state.light_enabled = false;
00091
00092 m_state.sten_enabled = false;
00093 m_state.sten_ref = 0;
00094 m_state.sten_buf = 0;
00095 m_state.sten_op = 0;
00096 m_state.sten_func = 0;
00097
00098 m_state.env_color[0] = 0;
00099 m_state.env_color[1] = 0;
00100 m_state.env_color[2] = 0;
00101 m_state.blend_src = GL_SRC_ALPHA;
00102 m_state.blend_dst = GL_ONE_MINUS_SRC_ALPHA;
00103 m_state.alpha_enabled = true;
00104 m_state.depth_enabled = true;
00105 m_state.scissor_test = true;
00106 }
00107
00108 RenderBackendOpenGLe::~RenderBackendOpenGLe() {
00109 glDeleteTextures(1, &m_mask_overlays);
00110 if(GLEE_EXT_framebuffer_object && m_useframebuffer) {
00111 glDeleteFramebuffers(1, &m_fbo_id);
00112 }
00113 deinit();
00114 }
00115
00116 const std::string& RenderBackendOpenGLe::getName() const {
00117 static std::string backend_name = "OpenGLe";
00118 return backend_name;
00119 }
00120
00121 void RenderBackendOpenGLe::init(const std::string& driver) {
00122
00123 Uint32 flags = SDL_INIT_VIDEO;
00124 if (SDL_InitSubSystem(flags) < 0)
00125 throw SDLException(SDL_GetError());
00126 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
00127 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
00128
00129 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
00130 }
00131
00132 void RenderBackendOpenGLe::clearBackBuffer() {
00133 disableScissorTest();
00134 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00135 enableScissorTest();
00136 }
00137
00138 void RenderBackendOpenGLe::createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon){
00139 if(icon != "") {
00140 SDL_Surface *img = IMG_Load(icon.c_str());
00141 if(img != NULL) {
00142 SDL_WM_SetIcon(img, 0);
00143 SDL_FreeSurface(img);
00144 }
00145 }
00146
00147 setScreenMode(mode);
00148 SDL_WM_SetCaption(title.c_str(), 0);
00149 }
00150
00151 void RenderBackendOpenGLe::setScreenMode(const ScreenMode& mode) {
00152 uint16_t width = mode.getWidth();
00153 uint16_t height = mode.getHeight();
00154 uint16_t bitsPerPixel = mode.getBPP();
00155 bool fs = mode.isFullScreen();
00156 uint32_t flags = mode.getSDLFlags();
00157
00158 if (bitsPerPixel != 0) {
00159 uint16_t bpp = SDL_VideoModeOK(width, height, bitsPerPixel, flags);
00160 if (!bpp){
00161 throw SDLException("Selected video mode not supported!");
00162 }
00163 }
00164
00165 if(m_screen) {
00166 SDL_FreeSurface(m_screen);
00167 }
00168 m_screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags);
00169 if( !m_screen ) {
00170 throw SDLException("Unable to set video mode selected!");
00171 }
00172 m_target = m_screen;
00173
00174 FL_LOG(_log, LMsg("RenderBackendOpenGLe")
00175 << "Videomode " << width << "x" << height
00176 << " at " << int32_t(bitsPerPixel) << " bpp");
00177
00178 m_rgba_format = *(m_screen->format);
00179 m_rgba_format.Rmask = RMASK;
00180 m_rgba_format.Gmask = GMASK;
00181 m_rgba_format.Bmask = BMASK;
00182 m_rgba_format.Amask = AMASK;
00183
00184
00185 m_screenMode = ScreenMode(width,
00186 height,
00187 bitsPerPixel,
00188 m_screen->flags);
00189
00190 if (!m_screen) {
00191 throw SDLException(SDL_GetError());
00192 }
00193
00194 glViewport(0, 0, width, height);
00195 glMatrixMode(GL_PROJECTION);
00196 glLoadIdentity();
00197 glOrtho(0, width, height, 0, znear, zfar);
00198 glMatrixMode(GL_MODELVIEW);
00199 glLoadIdentity();
00200
00201 glEnable(GL_CULL_FACE);
00202 glFrontFace(GL_CCW);
00203 glCullFace(GL_BACK);
00204
00205 glPixelStorei(GL_PACK_ALIGNMENT, 1);
00206 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00207
00208 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
00209 glClearDepth(1.0f);
00210 glClearStencil(0);
00211
00212 glEnable(GL_BLEND);
00213 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00214 glEnable(GL_ALPHA_TEST);
00215 glAlphaFunc(GL_GREATER, ALPHA_REF);
00216 glEnable(GL_DEPTH_TEST);
00217 glDepthFunc(GL_LEQUAL);
00218
00219 glEnable(GL_SCISSOR_TEST);
00220
00221 glEnableClientState(GL_VERTEX_ARRAY);
00222
00223 prepareForOverlays();
00224
00225 glPointSize(1.0);
00226 glLineWidth(1.0);
00227
00228 if(GLEE_EXT_framebuffer_object && m_useframebuffer) {
00229 glGenFramebuffers(1, &m_fbo_id);
00230 }
00231
00232 m_renderZ_datas.resize(buffer_default_size);
00233 }
00234
00235 void RenderBackendOpenGLe::startFrame() {
00236 RenderBackend::startFrame();
00237 }
00238
00239 void RenderBackendOpenGLe::endFrame() {
00240 SDL_GL_SwapBuffers();
00241 RenderBackend::endFrame();
00242 }
00243
00244 Image* RenderBackendOpenGLe::createImage(IResourceLoader* loader) {
00245 return new GLeImage(loader);
00246 }
00247
00248 Image* RenderBackendOpenGLe::createImage(const std::string& name, IResourceLoader* loader) {
00249 return new GLeImage(name, loader);
00250 }
00251
00252 Image* RenderBackendOpenGLe::createImage(SDL_Surface* surface) {
00253
00254
00255
00256
00257
00258
00259 if (32 == surface->format->BitsPerPixel
00260 && m_rgba_format.Rmask == surface->format->Rmask
00261 && m_rgba_format.Gmask == surface->format->Gmask
00262 && m_rgba_format.Bmask == surface->format->Bmask
00263 && m_rgba_format.Amask == surface->format->Amask
00264 && m_rgba_format.Rshift == surface->format->Rshift
00265 && m_rgba_format.Gshift == surface->format->Gshift
00266 && m_rgba_format.Bshift == surface->format->Bshift
00267 && m_rgba_format.Ashift == surface->format->Ashift
00268 && m_rgba_format.Rloss == surface->format->Rloss
00269 && m_rgba_format.Gloss == surface->format->Gloss
00270 && m_rgba_format.Bloss == surface->format->Bloss
00271 && m_rgba_format.Aloss == surface->format->Aloss
00272 && surface->flags & SDL_SRCALPHA ) {
00273
00274 return new GLeImage(surface);
00275 }
00276
00277 uint8_t bpp = m_rgba_format.BitsPerPixel;
00278 m_rgba_format.BitsPerPixel = 32;
00279 SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA);
00280 m_rgba_format.BitsPerPixel = bpp;
00281 GLeImage* image = new GLeImage(conv);
00282 SDL_FreeSurface( surface );
00283 return image;
00284 }
00285
00286 Image* RenderBackendOpenGLe::createImage(const std::string& name, SDL_Surface* surface) {
00287
00288
00289
00290
00291
00292
00293 if (32 == surface->format->BitsPerPixel
00294 && m_rgba_format.Rmask == surface->format->Rmask
00295 && m_rgba_format.Gmask == surface->format->Gmask
00296 && m_rgba_format.Bmask == surface->format->Bmask
00297 && m_rgba_format.Amask == surface->format->Amask
00298 && m_rgba_format.Rshift == surface->format->Rshift
00299 && m_rgba_format.Gshift == surface->format->Gshift
00300 && m_rgba_format.Bshift == surface->format->Bshift
00301 && m_rgba_format.Ashift == surface->format->Ashift
00302 && m_rgba_format.Rloss == surface->format->Rloss
00303 && m_rgba_format.Gloss == surface->format->Gloss
00304 && m_rgba_format.Bloss == surface->format->Bloss
00305 && m_rgba_format.Aloss == surface->format->Aloss
00306 && surface->flags & SDL_SRCALPHA ) {
00307
00308 return new GLeImage(name, surface);
00309 }
00310
00311 uint8_t bpp = m_rgba_format.BitsPerPixel;
00312 m_rgba_format.BitsPerPixel = 32;
00313 SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA);
00314 m_rgba_format.BitsPerPixel = bpp;
00315 GLeImage* image = new GLeImage(name, conv);
00316 SDL_FreeSurface( surface );
00317 return image;
00318 }
00319
00320 Image* RenderBackendOpenGLe::createImage(const uint8_t* data, uint32_t width, uint32_t height) {
00321 return new GLeImage(data, width, height);
00322 }
00323
00324 Image* RenderBackendOpenGLe::createImage(const std::string& name, const uint8_t* data, uint32_t width, uint32_t height) {
00325 return new GLeImage(name, data, width, height);
00326 }
00327
00328 void RenderBackendOpenGLe::setLightingModel(uint32_t lighting) {
00329 if (m_state.lightmodel != lighting) {
00330 if (m_state.lightmodel != 0) {
00331 disableLighting();
00332 glDisable(GL_COLOR_MATERIAL);
00333 } else if (lighting != 0) {
00334 m_state.lightmodel = lighting;
00335 enableLighting();
00336 glEnable(GL_LIGHT0);
00337 glColorMaterial(GL_FRONT, GL_DIFFUSE);
00338 glEnable(GL_COLOR_MATERIAL);
00339 }
00340 m_state.lightmodel = lighting;
00341 }
00342 }
00343
00344 uint32_t RenderBackendOpenGLe::getLightingModel() const {
00345 return m_state.lightmodel;
00346 }
00347
00348 void RenderBackendOpenGLe::enableTextures(uint32_t texUnit) {
00349 if(m_state.tex_enabled[texUnit] == false) {
00350 if(m_state.active_tex != texUnit) {
00351 m_state.active_tex = texUnit;
00352 glActiveTexture(GL_TEXTURE0 + texUnit);
00353 }
00354 m_state.tex_enabled[texUnit] = true;
00355
00356 glEnable(GL_TEXTURE_2D);
00357 if(texUnit == 0) {
00358 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00359 }
00360 }
00361 }
00362
00363 void RenderBackendOpenGLe::disableTextures(uint32_t texUnit)
00364 {
00365 if(m_state.tex_enabled[texUnit] == true) {
00366 if(m_state.active_tex != texUnit) {
00367 m_state.active_tex = texUnit;
00368 glActiveTexture(GL_TEXTURE0 + texUnit);
00369 }
00370 m_state.tex_enabled[texUnit] = false;
00371
00372 glDisable(GL_TEXTURE_2D);
00373 if(texUnit == 0) {
00374 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00375 }
00376 }
00377 }
00378
00379 void RenderBackendOpenGLe::bindTexture(uint32_t texUnit, GLuint texId) {
00380 enableTextures(texUnit);
00381
00382 if(m_state.texture[texUnit] != texId) {
00383 if(m_state.active_tex != texUnit) {
00384 m_state.active_tex = texUnit;
00385 glActiveTexture(GL_TEXTURE0 + texUnit);
00386 }
00387 m_state.texture[texUnit] = texId;
00388 glBindTexture(GL_TEXTURE_2D, texId);
00389 }
00390 }
00391
00392 void RenderBackendOpenGLe::bindTexture(GLuint texId) {
00393 if(m_state.texture[m_state.active_tex] != texId) {
00394 m_state.texture[m_state.active_tex] = texId;
00395 glBindTexture(GL_TEXTURE_2D, texId);
00396 }
00397 }
00398
00399 void RenderBackendOpenGLe::enableLighting() {
00400 if (m_state.lightmodel != 0 && !m_state.light_enabled) {
00401 glEnable(GL_LIGHTING);
00402 m_state.light_enabled = true;
00403 }
00404 }
00405
00406 void RenderBackendOpenGLe::disableLighting() {
00407 if (m_state.lightmodel != 0 && m_state.light_enabled) {
00408 glDisable(GL_LIGHTING);
00409 m_state.light_enabled = false;
00410 }
00411 }
00412
00413 void RenderBackendOpenGLe::setLighting(float red, float green, float blue) {
00414 if (m_state.lightmodel != 0) {
00415 GLfloat lightDiffuse[] = {red, green, blue, 1.0f};
00416 glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
00417 }
00418 }
00419
00420 void RenderBackendOpenGLe::resetLighting() {
00421 m_state.light_enabled = false;
00422 }
00423
00424 void RenderBackendOpenGLe::enableStencilTest() {
00425 if (!m_state.sten_enabled) {
00426 glEnable(GL_STENCIL_TEST);
00427 m_state.sten_enabled = true;
00428 }
00429 }
00430
00431 void RenderBackendOpenGLe::disableStencilTest() {
00432 if (m_state.sten_enabled) {
00433 glDisable(GL_STENCIL_TEST);
00434 m_state.sten_enabled = false;
00435 }
00436 }
00437
00438 void RenderBackendOpenGLe::setStencilTest(uint8_t stencil_ref, GLenum stencil_op, GLenum stencil_func) {
00439 enableStencilTest();
00440 if(m_state.sten_op != stencil_op) {
00441 m_state.sten_op = stencil_op;
00442 glStencilOp(GL_KEEP, GL_KEEP, m_state.sten_op);
00443 }
00444
00445 if(m_state.sten_ref != stencil_ref || m_state.sten_func != stencil_func) {
00446 m_state.sten_ref = stencil_ref;
00447 m_state.sten_func = stencil_func;
00448 glStencilFunc(m_state.sten_func, stencil_ref, 0xff);
00449 }
00450 }
00451
00452 void RenderBackendOpenGLe::resetStencilBuffer(uint8_t buffer) {
00453 if (buffer != m_state.sten_buf) {
00454 m_state.sten_buf = buffer;
00455 glClearStencil(buffer);
00456 }
00457 disableScissorTest();
00458 glClear(GL_STENCIL_BUFFER_BIT);
00459 enableScissorTest();
00460 }
00461
00462 void RenderBackendOpenGLe::enableAlphaTest() {
00463 if (!m_state.alpha_enabled) {
00464 glEnable(GL_ALPHA_TEST);
00465 m_state.alpha_enabled = true;
00466 }
00467 }
00468
00469 void RenderBackendOpenGLe::disableAlphaTest() {
00470 if (m_state.alpha_enabled) {
00471 glDisable(GL_ALPHA_TEST);
00472 m_state.alpha_enabled = false;
00473 }
00474 }
00475
00476 void RenderBackendOpenGLe::setAlphaTest(float ref_alpha) {
00477 enableAlphaTest();
00478 glAlphaFunc(GL_GREATER, ref_alpha);
00479 }
00480
00481 void RenderBackendOpenGLe::enableDepthTest() {
00482 if (!m_state.depth_enabled) {
00483 glEnable(GL_DEPTH_TEST);
00484 m_state.depth_enabled = true;
00485 }
00486 }
00487
00488 void RenderBackendOpenGLe::disableDepthTest() {
00489 if (m_state.depth_enabled) {
00490 glDisable(GL_DEPTH_TEST);
00491 m_state.depth_enabled = false;
00492 }
00493 }
00494
00495 void RenderBackendOpenGLe::setEnvironmentalColor(const uint8_t* rgb) {
00496 if (memcmp(m_state.env_color, rgb, sizeof(uint8_t) * 3)) {
00497 memcpy(m_state.env_color, rgb, sizeof(uint8_t) * 3);
00498 GLfloat rgbf[4] = {
00499 static_cast<float>(m_state.env_color[0]) / 255.0f,
00500 static_cast<float>(m_state.env_color[1]) / 255.0f,
00501 static_cast<float>(m_state.env_color[2]) / 255.0f, 0.0f};
00502 glActiveTexture(GL_TEXTURE1);
00503 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgbf);
00504 glActiveTexture(GL_TEXTURE0);
00505 }
00506 }
00507
00508 void RenderBackendOpenGLe::enableScissorTest() {
00509 if(m_state.scissor_test == false) {
00510 m_state.scissor_test = true;
00511 glEnable(GL_SCISSOR_TEST);
00512 }
00513 }
00514
00515 void RenderBackendOpenGLe::disableScissorTest() {
00516 if(m_state.scissor_test == true) {
00517 m_state.scissor_test = false;
00518 glDisable(GL_SCISSOR_TEST);
00519 }
00520 }
00521
00522 void RenderBackendOpenGLe::changeBlending(int32_t src, int32_t dst) {
00523 GLenum src_fact;
00524 GLenum dst_fact;
00525
00526 switch(src) {
00527 case 0 : src_fact = GL_ZERO; break;
00528 case 1 : src_fact = GL_ONE; break;
00529 case 2 : src_fact = GL_DST_COLOR; break;
00530 case 3 : src_fact = GL_ONE_MINUS_DST_COLOR; break;
00531 case 4 : src_fact = GL_SRC_ALPHA; break;
00532 case 5 : src_fact = GL_ONE_MINUS_SRC_ALPHA; break;
00533 case 6 : src_fact = GL_DST_ALPHA; break;
00534 case 7 : src_fact = GL_ONE_MINUS_DST_ALPHA; break;
00535
00536 default : src_fact = GL_DST_COLOR; break;
00537 }
00538
00539 switch(dst) {
00540 case 0 : dst_fact = GL_ZERO; break;
00541 case 1 : dst_fact = GL_ONE; break;
00542 case 2 : dst_fact = GL_SRC_COLOR; break;
00543 case 3 : dst_fact = GL_ONE_MINUS_SRC_COLOR; break;
00544 case 4 : dst_fact = GL_SRC_ALPHA; break;
00545 case 5 : dst_fact = GL_ONE_MINUS_SRC_ALPHA; break;
00546 case 6 : dst_fact = GL_DST_ALPHA; break;
00547 case 7 : dst_fact = GL_ONE_MINUS_DST_ALPHA; break;
00548
00549 default : dst_fact = GL_SRC_ALPHA; break;
00550 }
00551
00552 if (m_state.blend_src != src_fact || m_state.blend_dst != dst_fact) {
00553 m_state.blend_src = src_fact;
00554 m_state.blend_dst = dst_fact;
00555 glBlendFunc(src_fact, dst_fact);
00556 }
00557 }
00558
00559 void RenderBackendOpenGLe::changeRenderInfos(uint16_t elements, int32_t src, int32_t dst, bool light,
00560 bool stentest, uint8_t stenref, GLConstants stenop, GLConstants stenfunc) {
00561
00562 uint16_t count = 0;
00563 uint32_t size = m_render_objects.size();
00564 while (count != elements) {
00565 ++count;
00566 RenderObject& r = m_render_objects.at(size-count);
00567
00568 r.src = src;
00569 r.dst = dst;
00570 r.light = light;
00571 if (stentest) {
00572 r.stencil_test = stentest;
00573 r.stencil_ref = stenref;
00574 r.stencil_op = stenop;
00575 r.stencil_func = stenfunc;
00576 }
00577 }
00578 }
00579
00580 void RenderBackendOpenGLe::renderVertexArrays() {
00581
00582
00583
00584
00585
00586 if(!m_renderZ_objects.empty() || !m_renderZ_objects_forced.empty()) {
00587 renderWithZ();
00588 }
00589
00590
00591
00592
00593
00594 if(!m_render_objects.empty()) {
00595 renderWithoutZ();
00596 }
00597 }
00598
00599 void RenderBackendOpenGLe::renderWithZ() {
00600 enableAlphaTest();
00601 enableDepthTest();
00602 enableTextures(0);
00603 enableLighting();
00604 glDisableClientState(GL_COLOR_ARRAY);
00605
00606 {
00607 static const uint32_t stride = sizeof(RenderZData);
00608
00609 glVertexPointer(3, GL_FLOAT, stride, &m_renderZ_datas[0].vertex);
00610 glTexCoordPointer(2, GL_FLOAT, stride, &m_renderZ_datas[0].texel);
00611
00612 std::vector<RenderZObject>::iterator iter = m_renderZ_objects.begin();
00613 for ( ; iter != m_renderZ_objects.end(); ++iter) {
00614 bindTexture(iter->texture_id);
00615 glDrawArrays(GL_QUADS, iter->index, iter->elements);
00616 }
00617 m_renderZ_objects.clear();
00618 }
00619
00620
00621 if (!m_renderZ_objects_forced.empty()) {
00622 static const uint32_t stride = sizeof(RenderZData);
00623
00624
00625 glVertexPointer(3, GL_FLOAT, stride, &m_renderZ_datas[0].vertex);
00626 glTexCoordPointer(2, GL_FLOAT, stride, &m_renderZ_datas[0].texel);
00627 setStencilTest(255, GL_REPLACE, GL_ALWAYS);
00628 disableLighting();
00629
00630 std::vector<RenderZObject>::iterator iter = m_renderZ_objects_forced.begin();
00631 for ( ; iter != m_renderZ_objects_forced.end(); ++iter) {
00632 bindTexture(iter->texture_id);
00633 glDrawArrays(GL_QUADS, iter->index, iter->elements);
00634 }
00635 disableStencilTest();
00636 enableLighting();
00637 m_renderZ_objects_forced.clear();
00638 }
00639
00640
00641 glEnableClientState(GL_COLOR_ARRAY);
00642
00643
00644 if (!m_render_objects2T.empty()) {
00645 static const uint32_t stride = sizeof(RenderZData2T);
00646
00647 glActiveTexture(GL_TEXTURE1);
00648 glEnable(GL_TEXTURE_2D);
00649 glActiveTexture(GL_TEXTURE0);
00650
00651 glVertexPointer(3, GL_FLOAT, stride, &m_render_datas2T[0].vertex);
00652 glColorPointer(4, GL_UNSIGNED_BYTE, stride, &m_render_datas2T[0].color);
00653
00654 glClientActiveTexture(GL_TEXTURE1);
00655 glTexCoordPointer(2, GL_FLOAT, stride, &m_render_datas2T[0].texel2);
00656 glClientActiveTexture(GL_TEXTURE0);
00657 glTexCoordPointer(2, GL_FLOAT, stride, &m_render_datas2T[0].texel);
00658
00659
00660 GLint index = 0;
00661
00662 GLsizei elements = 0;
00663
00664 uint32_t texture_id = 0;
00665
00666 uint8_t rgb[3] = {0};
00667
00668 std::vector<RenderObject>::iterator iter = m_render_objects2T.begin();
00669 for (; iter != m_render_objects2T.end(); ++iter) {
00670 if (iter->texture_id != texture_id || memcmp(rgb, iter->rgb, sizeof(uint8_t)*3)) {
00671 if (elements > 0) {
00672 glDrawArrays(GL_QUADS, index, elements);
00673 index += elements;
00674 }
00675
00676 setEnvironmentalColor(iter->rgb);
00677 bindTexture(iter->texture_id);
00678 texture_id = iter->texture_id;
00679 elements = iter->size;;
00680 memcpy(rgb, iter->rgb, sizeof(uint8_t)*3);
00681 } else {
00682 elements += iter->size;
00683 }
00684 }
00685 glDrawArrays(GL_QUADS, index, elements);
00686
00687 glActiveTexture(GL_TEXTURE1);
00688 glDisable(GL_TEXTURE_2D);
00689 glActiveTexture(GL_TEXTURE0);
00690
00691 m_render_objects2T.clear();
00692 m_render_datas2T.clear();
00693 }
00694
00695
00696 disableAlphaTest();
00697
00698
00699 if (!m_render_trans_objects.empty()) {
00700 static const uint32_t stride = sizeof(RenderZData2T);
00701
00702 glVertexPointer(3, GL_FLOAT, stride, &m_render_trans_datas[0].vertex);
00703 glColorPointer(4, GL_UNSIGNED_BYTE, stride, &m_render_trans_datas[0].color);
00704 glClientActiveTexture(GL_TEXTURE0);
00705 glTexCoordPointer(2, GL_FLOAT, stride, &m_render_trans_datas[0].texel);
00706
00707
00708 GLint index = 0;
00709
00710 GLsizei elements = 0;
00711
00712 uint32_t texture_id = 0;
00713
00714 GLfloat rgb[3] = {0};
00715
00716 std::vector<RenderObject>::iterator iter = m_render_trans_objects.begin();
00717 for( ; iter != m_render_trans_objects.end(); ++iter) {
00718 if (iter->texture_id != texture_id) {
00719 if (elements > 0) {
00720 glDrawArrays(GL_QUADS, index, elements);
00721 index += elements;
00722 }
00723
00724 bindTexture(iter->texture_id);
00725 texture_id = iter->texture_id;
00726 elements = iter->size;;
00727 } else {
00728 elements += iter->size;
00729 }
00730 }
00731 glDrawArrays(GL_QUADS, index, elements);
00732
00733 m_render_trans_datas.clear();
00734 m_render_trans_objects.clear();
00735 }
00736
00737 disableTextures(0);
00738 disableDepthTest();
00739 disableLighting();
00740 }
00741
00742 void RenderBackendOpenGLe::renderWithoutZ() {
00743
00744 bool type = false;
00745 bool texture = false;
00746 bool render = false;
00747 bool blending = false;
00748 bool stencil = false;
00749
00750 static const uint32_t stride = sizeof(RenderData);
00751
00752 glEnableClientState(GL_COLOR_ARRAY);
00753 glVertexPointer(2, GL_FLOAT, stride, &m_render_datas[0].vertex);
00754 glTexCoordPointer(2, GL_FLOAT, stride, &m_render_datas[0].texel);
00755 glColorPointer(4, GL_UNSIGNED_BYTE, stride, &m_render_datas[0].color);
00756
00757 disableAlphaTest();
00758 disableDepthTest();
00759 disableTextures(0);
00760
00761
00762 int32_t index = 0;
00763
00764 uint32_t elements = 0;
00765
00766 GLenum mode = GL_QUADS;
00767
00768 uint32_t texture_id = 0;
00769
00770 int32_t src = 4;
00771
00772 int32_t dst = 5;
00773
00774 for(std::vector<RenderObject>::iterator iter = m_render_objects.begin(); iter != m_render_objects.end(); ++iter) {
00775
00776 if (iter->mode != mode) {
00777 type = true;
00778 render = true;
00779 }
00780 if (iter->texture_id != texture_id) {
00781 texture = true;
00782 render = true;
00783 }
00784 if (m_state.lightmodel != 0) {
00785 if (iter->src != src || iter->dst != dst) {
00786 blending = true;
00787 render = true;
00788 }
00789
00790 if (iter->stencil_test != m_state.sten_enabled) {
00791 stencil = true;
00792 render = true;
00793 }
00794 if (iter->stencil_ref != m_state.sten_ref ||
00795 iter->stencil_op != m_state.sten_op ||
00796 iter->stencil_func != m_state.sten_func) {
00797 stencil = true;
00798 render = true;
00799 }
00800 }
00801
00802
00803 if (!render) {
00804 elements += iter->size;
00805
00806 } else {
00807 if (elements > 0) {
00808
00809 glDrawArrays(mode, index, elements);
00810 index += elements;
00811 }
00812
00813 elements = iter->size;
00814
00815
00816 if (type) {
00817 mode = iter->mode;
00818 type = false;
00819 }
00820
00821 if (texture) {
00822 if (iter->texture_id != 0) {
00823 enableTextures(0);
00824 bindTexture(iter->texture_id);
00825 texture_id = iter->texture_id;
00826 } else {
00827 disableTextures(0);
00828 texture_id = 0;
00829 }
00830 texture = false;
00831 }
00832
00833 if (m_state.lightmodel != 0) {
00834
00835 if (blending) {
00836 src = iter->src;
00837 dst = iter->dst;
00838 changeBlending(src, dst);
00839 blending = false;
00840 }
00841
00842 if (stencil) {
00843 if (iter->stencil_test) {
00844 setStencilTest(iter->stencil_ref, iter->stencil_op, iter->stencil_func);
00845 enableAlphaTest();
00846 } else {
00847 disableStencilTest();
00848 disableAlphaTest();
00849 }
00850 stencil = false;
00851 }
00852 }
00853
00854 render = false;
00855 }
00856 }
00857
00858 glDrawArrays(mode, index, elements);
00859
00860 changeBlending(4, 5);
00861 disableStencilTest();
00862 disableTextures(0);
00863
00864
00865 glDisableClientState(GL_COLOR_ARRAY);
00866
00867 m_render_objects.clear();
00868 m_render_datas.clear();
00869 }
00870
00871 bool RenderBackendOpenGLe::putPixel(int32_t x, int32_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00872 if ((x < 0) || (x >= (int32_t)m_target->w) ||
00873 (y < 0) || (y >= (int32_t)m_target->h)) {
00874 return false;
00875 }
00876 RenderData rd;
00877 rd.vertex[0] = static_cast<float>(x);
00878 rd.vertex[1] = static_cast<float>(y);
00879 rd.color[0] = r;
00880 rd.color[1] = g;
00881 rd.color[2] = b;
00882 rd.color[3] = a;
00883 m_render_datas.push_back(rd);
00884
00885 RenderObject ro(GL_POINTS, 1);
00886 m_render_objects.push_back(ro);
00887
00888 return true;
00889 }
00890
00891 void RenderBackendOpenGLe::drawLine(const Point& p1, const Point& p2, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00892 RenderData rd;
00893 rd.vertex[0] = static_cast<float>(p1.x);
00894 rd.vertex[1] = static_cast<float>(p1.y);
00895 rd.color[0] = r;
00896 rd.color[1] = g;
00897 rd.color[2] = b;
00898 rd.color[3] = a;
00899 m_render_datas.push_back(rd);
00900
00901 rd.vertex[0] = static_cast<float>(p2.x);
00902 rd.vertex[1] = static_cast<float>(p2.y);
00903 m_render_datas.push_back(rd);
00904
00905 RenderObject ro(GL_LINES, 2);
00906 m_render_objects.push_back(ro);
00907 }
00908
00909 void RenderBackendOpenGLe::drawTriangle(const Point& p1, const Point& p2, const Point& p3, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00910 RenderData rd;
00911 rd.vertex[0] = static_cast<float>(p1.x);
00912 rd.vertex[1] = static_cast<float>(p1.y);
00913 rd.color[0] = r;
00914 rd.color[1] = g;
00915 rd.color[2] = b;
00916 rd.color[3] = a;
00917 m_render_datas.push_back(rd);
00918
00919 rd.vertex[0] = static_cast<float>(p2.x);
00920 rd.vertex[1] = static_cast<float>(p2.y);
00921 m_render_datas.push_back(rd);
00922
00923 rd.vertex[0] = static_cast<float>(p3.x);
00924 rd.vertex[1] = static_cast<float>(p3.y);
00925 m_render_datas.push_back(rd);
00926
00927 RenderObject ro(GL_TRIANGLES, 3);
00928 m_render_objects.push_back(ro);
00929 }
00930
00931 void RenderBackendOpenGLe::drawRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00932 RenderData rd;
00933 rd.vertex[0] = static_cast<float>(p.x);
00934 rd.vertex[1] = static_cast<float>(p.y);
00935 rd.color[0] = r;
00936 rd.color[1] = g;
00937 rd.color[2] = b;
00938 rd.color[3] = a;
00939 m_render_datas.push_back(rd);
00940 rd.vertex[0] = static_cast<float>(p.x+w);
00941
00942 m_render_datas.push_back(rd);
00943 rd.vertex[1] = static_cast<float>(p.y+h);
00944
00945 m_render_datas.push_back(rd);
00946 rd.vertex[0] = static_cast<float>(p.x);
00947 m_render_datas.push_back(rd);
00948
00949 RenderObject ro(GL_LINE_LOOP, 4);
00950 m_render_objects.push_back(ro);
00951 }
00952
00953 void RenderBackendOpenGLe::fillRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00954 RenderData rd;
00955 rd.vertex[0] = static_cast<float>(p.x);
00956 rd.vertex[1] = static_cast<float>(p.y);
00957 rd.color[0] = r;
00958 rd.color[1] = g;
00959 rd.color[2] = b;
00960 rd.color[3] = a;
00961 m_render_datas.push_back(rd);
00962
00963 rd.vertex[1] = static_cast<float>(p.y+h);
00964 m_render_datas.push_back(rd);
00965
00966 rd.vertex[0] = static_cast<float>(p.x+w);
00967 m_render_datas.push_back(rd);
00968
00969 rd.vertex[1] = static_cast<float>(p.y);
00970 m_render_datas.push_back(rd);
00971
00972 RenderObject ro(GL_QUADS, 4);
00973 m_render_objects.push_back(ro);
00974 }
00975
00976 void RenderBackendOpenGLe::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) {
00977 RenderData rd;
00978 rd.vertex[0] = static_cast<float>(p1.x);
00979 rd.vertex[1] = static_cast<float>(p1.y);
00980 rd.color[0] = r;
00981 rd.color[1] = g;
00982 rd.color[2] = b;
00983 rd.color[3] = a;
00984 m_render_datas.push_back(rd);
00985
00986 rd.vertex[0] = static_cast<float>(p2.x);
00987 rd.vertex[1] = static_cast<float>(p2.y);
00988 m_render_datas.push_back(rd);
00989
00990 rd.vertex[0] = static_cast<float>(p3.x);
00991 rd.vertex[1] = static_cast<float>(p3.y);
00992 m_render_datas.push_back(rd);
00993
00994 rd.vertex[0] = static_cast<float>(p4.x);
00995 rd.vertex[1] = static_cast<float>(p4.y);
00996 m_render_datas.push_back(rd);
00997
00998 RenderObject ro(GL_QUADS, 4);
00999 m_render_objects.push_back(ro);
01000 }
01001
01002 void RenderBackendOpenGLe::drawVertex(const Point& p, const uint8_t size, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
01003 RenderData rd;
01004 rd.vertex[0] = static_cast<float>(p.x-size);
01005 rd.vertex[1] = static_cast<float>(p.y+size);
01006 rd.color[0] = r;
01007 rd.color[1] = g;
01008 rd.color[2] = b;
01009 rd.color[3] = a;
01010 m_render_datas.push_back(rd);
01011
01012 rd.vertex[0] = static_cast<float>(p.x+size);
01013 m_render_datas.push_back(rd);
01014
01015 rd.vertex[1] = static_cast<float>(p.y-size);
01016 m_render_datas.push_back(rd);
01017
01018 rd.vertex[0] = static_cast<float>(p.x-size);
01019 m_render_datas.push_back(rd);
01020
01021 RenderObject ro(GL_LINE_LOOP, 4);
01022 m_render_objects.push_back(ro);
01023 }
01024
01025 void RenderBackendOpenGLe::drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int32_t subdivisions,
01026 float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue) {
01027 const float step = Mathf::twoPi()/subdivisions;
01028 RenderData rd;;
01029 for(float angle=0; angle<=Mathf::twoPi(); angle+=step){
01030 rd.vertex[0] = static_cast<float>(p.x);
01031 rd.vertex[1] = static_cast<float>(p.y);
01032 rd.color[0] = red;
01033 rd.color[1] = green;
01034 rd.color[2] = blue;
01035 rd.color[3] = intensity;
01036 m_render_datas.push_back(rd);
01037
01038 rd.vertex[0] = radius*Mathf::Cos(angle+step)*xstretch + p.x;
01039 rd.vertex[1] = radius*Mathf::Sin(angle+step)*ystretch + p.y;
01040 rd.color[0] = 0;
01041 rd.color[1] = 0;
01042 rd.color[2] = 0;
01043 rd.color[3] = 255;
01044 m_render_datas.push_back(rd);
01045
01046 rd.vertex[0] = radius*Mathf::Cos(angle)*xstretch + p.x;
01047 rd.vertex[1] = radius*Mathf::Sin(angle)*ystretch + p.y;
01048 m_render_datas.push_back(rd);
01049
01050 RenderObject ro(GL_TRIANGLES, 3);
01051 m_render_objects.push_back(ro);
01052 }
01053 }
01054
01055 void RenderBackendOpenGLe::addImageToArray(uint32_t id, const Rect& rect, float const* st, uint8_t alpha, uint8_t const* rgb) {
01056 RenderData rd;
01057 rd.vertex[0] = static_cast<float>(rect.x);
01058 rd.vertex[1] = static_cast<float>(rect.y);
01059 rd.texel[0] = st[0];
01060 rd.texel[1] = st[1];
01061 rd.color[0] = 255;
01062 rd.color[1] = 255;
01063 rd.color[2] = 255;
01064 rd.color[3] = alpha;
01065 m_render_datas.push_back(rd);
01066
01067 rd.vertex[0] = static_cast<float>(rect.x);
01068 rd.vertex[1] = static_cast<float>(rect.y+rect.h);
01069 rd.texel[1] = st[3];
01070 m_render_datas.push_back(rd);
01071
01072 rd.vertex[0] = static_cast<float>(rect.x+rect.w);
01073 rd.vertex[1] = static_cast<float>(rect.y+rect.h);
01074 rd.texel[0] = st[2];
01075 m_render_datas.push_back(rd);
01076
01077 rd.vertex[0] = static_cast<float>(rect.x+rect.w);
01078 rd.vertex[1] = static_cast<float>(rect.y);
01079 rd.texel[1] = st[1];
01080 m_render_datas.push_back(rd);
01081
01082 RenderObject ro(GL_QUADS, 4, id);
01083 m_render_objects.push_back(ro);
01084 }
01085
01086 RenderBackendOpenGLe::RenderZObject* RenderBackendOpenGLe::getRenderBufferObject(GLuint texture_id, bool forceNewBatch) {
01087 if (!forceNewBatch) {
01088 for (std::vector<RenderZObject>::iterator it = m_renderZ_objects.begin(); it != m_renderZ_objects.end(); ++it) {
01089 if (it->texture_id == texture_id) {
01090 if (it->elements < it->max_size - 4) {
01091 return &(*it);
01092 }
01093 }
01094 }
01095 }
01096 static int last_forced = 0;
01097
01098
01099 RenderZObject obj;
01100 if (!m_renderZ_objects.empty()) {
01101 obj.index = m_renderZ_objects.back().index + m_renderZ_objects.back().max_size;
01102 obj.index += last_forced * 4;
01103 } else {
01104 obj.index = 0;
01105 }
01106 obj.texture_id = texture_id;
01107 obj.elements = 0;
01108 obj.max_size = forceNewBatch ? 4 : max_quads_per_texbatch * 4;
01109
01110 if (!forceNewBatch) {
01111 last_forced = 0;
01112 m_renderZ_objects.push_back(obj);
01113 return &m_renderZ_objects.back();
01114 } else {
01115 ++last_forced;
01116 m_renderZ_objects_forced.push_back(obj);
01117 return &m_renderZ_objects_forced.back();
01118 }
01119 }
01120
01121 void RenderBackendOpenGLe::addImageToArrayZ(uint32_t id, const Rect& rect, float vertexZ, float const* st, uint8_t alpha, bool forceNewBatch, uint8_t const* rgb) {
01122 if (alpha == 255) {
01123 if (rgb == NULL) {
01124
01125 RenderZObject* renderObj = getRenderBufferObject(id, forceNewBatch);
01126 uint32_t offset = renderObj->index + renderObj->elements;
01127 renderObj->elements += 4;
01128 RenderZData* rd;
01129
01130 rd = &m_renderZ_datas[offset];
01131 rd->vertex[0] = static_cast<float>(rect.x);
01132 rd->vertex[1] = static_cast<float>(rect.y);
01133 rd->vertex[2] = vertexZ;
01134 rd->texel[0] = st[0];
01135 rd->texel[1] = st[1];
01136
01137 ++rd;
01138 rd->vertex[0] = static_cast<float>(rect.x);
01139 rd->vertex[1] = static_cast<float>(rect.y+rect.h);
01140 rd->vertex[2] = vertexZ;
01141 rd->texel[0] = st[0];
01142 rd->texel[1] = st[3];
01143
01144 ++rd;
01145 rd->vertex[0] = static_cast<float>(rect.x+rect.w);
01146 rd->vertex[1] = static_cast<float>(rect.y+rect.h);
01147 rd->vertex[2] = vertexZ;
01148 rd->texel[0] = st[2];
01149 rd->texel[1] = st[3];
01150
01151 ++rd;
01152 rd->vertex[0] = static_cast<float>(rect.x+rect.w);
01153 rd->vertex[1] = static_cast<float>(rect.y);
01154 rd->vertex[2] = vertexZ;
01155 rd->texel[0] = st[2];
01156 rd->texel[1] = st[1];
01157 } else {
01158
01159 RenderZData2T rd;
01160 rd.vertex[0] = static_cast<float>(rect.x);
01161 rd.vertex[1] = static_cast<float>(rect.y);
01162 rd.vertex[2] = vertexZ;
01163 rd.texel[0] = st[0];
01164 rd.texel[1] = st[1];
01165 rd.texel2[0] = 0.0;
01166 rd.texel2[1] = 0.0;
01167 rd.color[0] = 255;
01168 rd.color[1] = 255;
01169 rd.color[2] = 255;
01170 rd.color[3] = 255;
01171 m_render_datas2T.push_back(rd);
01172
01173 rd.vertex[0] = static_cast<float>(rect.x);
01174 rd.vertex[1] = static_cast<float>(rect.y+rect.h);
01175 rd.texel[1] = st[3];
01176 rd.texel2[1] = 1.0;
01177 m_render_datas2T.push_back(rd);
01178
01179 rd.vertex[0] = static_cast<float>(rect.x+rect.w);
01180 rd.vertex[1] = static_cast<float>(rect.y+rect.h);
01181 rd.texel[0] = st[2];
01182 rd.texel2[0] = 1.0;
01183 m_render_datas2T.push_back(rd);
01184
01185 rd.vertex[0] = static_cast<float>(rect.x+rect.w);
01186 rd.vertex[1] = static_cast<float>(rect.y);
01187 rd.texel[1] = st[1];
01188 rd.texel2[1] = 0.0;
01189 m_render_datas2T.push_back(rd);
01190
01191 RenderObject ro(GL_QUADS, 4, id);
01192 ro.rgb[0] = rgb[0];
01193 ro.rgb[1] = rgb[1];
01194 ro.rgb[2] = rgb[2];
01195 m_render_objects2T.push_back(ro);
01196 }
01197 } else {
01198 RenderZData2T rd;
01199 rd.vertex[0] = static_cast<float>(rect.x);
01200 rd.vertex[1] = static_cast<float>(rect.y);
01201 rd.vertex[2] = vertexZ;
01202 rd.texel[0] = st[0];
01203 rd.texel[1] = st[1];
01204 rd.color[0] = 255;
01205 rd.color[1] = 255;
01206 rd.color[2] = 255;
01207 rd.color[3] = alpha;
01208 m_render_trans_datas.push_back(rd);
01209
01210 rd.vertex[0] = static_cast<float>(rect.x);
01211 rd.vertex[1] = static_cast<float>(rect.y+rect.h);
01212 rd.texel[1] = st[3];
01213 m_render_trans_datas.push_back(rd);
01214
01215 rd.vertex[0] = static_cast<float>(rect.x+rect.w);
01216 rd.vertex[1] = static_cast<float>(rect.y+rect.h);
01217 rd.texel[0] = st[2];
01218 m_render_trans_datas.push_back(rd);
01219
01220 rd.vertex[0] = static_cast<float>(rect.x+rect.w);
01221 rd.vertex[1] = static_cast<float>(rect.y);
01222 rd.texel[1] = st[1];
01223 m_render_trans_datas.push_back(rd);
01224
01225 RenderObject ro(GL_QUADS, 4, id);
01226 if (rgb != NULL) {
01227 RenderObject ro(GL_QUADS, 4, id);
01228 ro.rgb[0] = rgb[0];
01229 ro.rgb[1] = rgb[1];
01230 ro.rgb[2] = rgb[2];
01231 }
01232 m_render_trans_objects.push_back(ro);
01233
01234 }
01235 }
01236
01237 void RenderBackendOpenGLe::prepareForOverlays() {
01238 glActiveTexture(GL_TEXTURE1);
01239 glEnable(GL_TEXTURE_2D);
01240
01241 if(m_mask_overlays == 0) {
01242
01243 glGenTextures(1, &m_mask_overlays);
01244
01245 uint8_t dummydata[3] = {127, 127, 127};
01246 glBindTexture(GL_TEXTURE_2D, m_mask_overlays);
01247 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
01248 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
01249 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
01250 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
01251 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0,
01252 GL_RGB, GL_UNSIGNED_BYTE, dummydata);
01253 } else {
01254 glBindTexture(GL_TEXTURE_2D, m_mask_overlays);
01255 }
01256
01257 m_state.texture[1] = m_mask_overlays;
01258
01259 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
01260 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
01261 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
01262
01263
01264 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
01265 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
01266 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
01267 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
01268
01269
01270
01271
01272
01273
01274 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
01275 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
01276
01277
01278 glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE1);
01279 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
01280
01281
01282 glActiveTexture(GL_TEXTURE1);
01283 glDisable(GL_TEXTURE_2D);
01284 glActiveTexture(GL_TEXTURE0);
01285
01286
01287
01288 }
01289
01290 void RenderBackendOpenGLe::captureScreen(const std::string& filename) {
01291 const uint32_t swidth = getWidth();
01292 const uint32_t sheight = getHeight();
01293
01294 uint8_t *pixels;
01295 SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, sheight, 24,
01296 RMASK, GMASK, BMASK, NULLMASK);
01297
01298 if (!surface) {
01299 return;
01300 }
01301
01302 SDL_LockSurface(surface);
01303 pixels = new uint8_t[swidth * sheight * 3];
01304 glReadPixels(0, 0, swidth, sheight, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
01305 uint8_t *imagepixels = reinterpret_cast<uint8_t*>(surface->pixels);
01306
01307 for (int32_t y = (sheight - 1); y >= 0; --y) {
01308 uint8_t *rowbegin = pixels + y * swidth * 3;
01309 uint8_t *rowend = rowbegin + swidth * 3;
01310
01311 std::copy(rowbegin, rowend, imagepixels);
01312
01313
01314 imagepixels += surface->pitch;
01315 }
01316
01317 SDL_UnlockSurface(surface);
01318 Image::saveAsPng(filename, *surface);
01319
01320 SDL_FreeSurface(surface);
01321 delete[] pixels;
01322 }
01323
01324 void RenderBackendOpenGLe::captureScreen(const std::string& filename, uint32_t width, uint32_t height) {
01325 const uint32_t swidth = getWidth();
01326 const uint32_t sheight = getHeight();
01327 const bool same_size = (width == swidth && height == sheight);
01328
01329 if (width < 1 || height < 1) {
01330 return;
01331 }
01332
01333 if (same_size) {
01334 captureScreen(filename);
01335 return;
01336 }
01337
01338 uint8_t *pixels;
01339
01340 SDL_Surface* src = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth, sheight, 32,
01341 RMASK, GMASK, BMASK, AMASK);
01342
01343 if (!src) {
01344 return;
01345 }
01346
01347 if (SDL_MUSTLOCK(src)) {
01348 SDL_LockSurface(src);
01349 }
01350 pixels = new uint8_t[swidth * sheight * 4];
01351 glReadPixels(0, 0, swidth, sheight, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
01352
01353 uint8_t* imagepixels = reinterpret_cast<uint8_t*>(src->pixels);
01354
01355 for (int32_t y = (sheight - 1); y >= 0; --y) {
01356 uint8_t *rowbegin = pixels + y * swidth * 4;
01357 uint8_t *rowend = rowbegin + swidth * 4;
01358
01359 std::copy(rowbegin, rowend, imagepixels);
01360
01361
01362 imagepixels += src->pitch;
01363 }
01364
01365
01366 SDL_Surface* dst = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,
01367 RMASK, GMASK, BMASK, AMASK);
01368
01369 uint32_t* src_pointer = static_cast<uint32_t*>(src->pixels);
01370 uint32_t* src_help_pointer = src_pointer;
01371 uint32_t* dst_pointer = static_cast<uint32_t*>(dst->pixels);
01372
01373 int32_t x, y, *sx_ca, *sy_ca;
01374 int32_t sx = static_cast<int32_t>(0xffff * src->w / dst->w);
01375 int32_t sy = static_cast<int32_t>(0xffff * src->h / dst->h);
01376 int32_t sx_c = 0;
01377 int32_t sy_c = 0;
01378
01379
01380 int32_t* sx_a = new int32_t[dst->w + 1];
01381 sx_ca = sx_a;
01382 for (x = 0; x <= dst->w; x++) {
01383 *sx_ca = sx_c;
01384 sx_ca++;
01385 sx_c &= 0xffff;
01386 sx_c += sx;
01387 }
01388
01389 int32_t* sy_a = new int32_t[dst->h + 1];
01390 sy_ca = sy_a;
01391 for (y = 0; y <= dst->h; y++) {
01392 *sy_ca = sy_c;
01393 sy_ca++;
01394 sy_c &= 0xffff;
01395 sy_c += sy;
01396 }
01397 sy_ca = sy_a;
01398
01399
01400
01401 if (SDL_MUSTLOCK(dst)) {
01402 SDL_LockSurface(dst);
01403 }
01404
01405 for (y = 0; y < dst->h; y++) {
01406 src_pointer = src_help_pointer;
01407 sx_ca = sx_a;
01408 for (x = 0; x < dst->w; x++) {
01409 *dst_pointer = *src_pointer;
01410 sx_ca++;
01411 src_pointer += (*sx_ca >> 16);
01412 dst_pointer++;
01413 }
01414 sy_ca++;
01415 src_help_pointer = (uint32_t*)((uint8_t*)src_help_pointer + (*sy_ca >> 16) * src->pitch);
01416 }
01417
01418 if (SDL_MUSTLOCK(dst)) {
01419 SDL_UnlockSurface(dst);
01420 }
01421 if (SDL_MUSTLOCK(src)) {
01422 SDL_UnlockSurface(src);
01423 }
01424
01425 Image::saveAsPng(filename, *dst);
01426
01427
01428 SDL_FreeSurface(src);
01429 SDL_FreeSurface(dst);
01430 delete[] sx_a;
01431 delete[] sy_a;
01432 delete[] pixels;
01433 }
01434
01435 void RenderBackendOpenGLe::setClipArea(const Rect& cliparea, bool clear) {
01436 glScissor(cliparea.x, getHeight() - cliparea.y - cliparea.h, cliparea.w, cliparea.h);
01437 if (clear) {
01438 if (m_isbackgroundcolor) {
01439 float red = float(m_backgroundcolor.r/255.0);
01440 float green = float(m_backgroundcolor.g/255.0);
01441 float blue = float(m_backgroundcolor.b/255.0);
01442 glClearColor(red, green, blue, 0.0);
01443 m_isbackgroundcolor = false;
01444 }
01445 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01446 }
01447 }
01448
01449 void RenderBackendOpenGLe::attachRenderTarget(ImagePtr& img, bool discard) {
01450 m_img_target = img;
01451 m_target_discard = discard;
01452
01453
01454 m_img_target->forceLoadInternal();
01455 m_target = m_img_target->getSurface();
01456
01457 GLeImage* glimage = static_cast<GLeImage*>(m_img_target.get());
01458
01459 GLuint targetid = glimage->getTexId();
01460 uint32_t w = m_img_target->getWidth();
01461 uint32_t h = m_img_target->getHeight();
01462
01463
01464 if(glimage->isCompressed()) {
01465 bindTexture(targetid);
01466 GLubyte* pixels = new GLubyte[w*h*4];
01467
01468 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
01469 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
01470 delete [] pixels;
01471 glimage->setCompressed(false);
01472 }
01473
01474
01475 if (GLEE_EXT_framebuffer_object && m_useframebuffer) {
01476 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo_id);
01477 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
01478 GL_TEXTURE_2D, targetid, 0);
01479 }
01480
01481 glViewport(0, 0, w, h);
01482 glMatrixMode(GL_PROJECTION);
01483 glLoadIdentity();
01484
01485 glOrtho(0, w, 0, h, -1, 1);
01486 glMatrixMode(GL_MODELVIEW);
01487
01488 glCullFace(GL_FRONT);
01489
01490 if (m_target_discard) {
01491 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01492 } else if (!m_target_discard && (!GLEE_EXT_framebuffer_object || !m_useframebuffer)) {
01493
01494 addImageToArray(targetid, m_img_target->getArea(),
01495 static_cast<GLeImage*>(m_img_target.get())->getTexCoords(), 255, 0);
01496
01497 renderWithoutZ();
01498 }
01499 }
01500
01501 void RenderBackendOpenGLe::detachRenderTarget() {
01502 assert(m_target != m_screen);
01503
01504
01505 renderVertexArrays();
01506
01507 if (GLEE_EXT_framebuffer_object && m_useframebuffer) {
01508 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
01509 } else {
01510 bindTexture(0, static_cast<GLeImage*>(m_img_target.get())->getTexId());
01511 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0,
01512 m_img_target->getWidth(), m_img_target->getHeight(), 0);
01513 glClear(GL_DEPTH_BUFFER_BIT);
01514 }
01515
01516 m_target = m_screen;
01517 glViewport(0, 0, m_screen->w, m_screen->h);
01518 glMatrixMode(GL_PROJECTION);
01519 glLoadIdentity();
01520 glOrtho(0, m_screen->w, m_screen->h, 0, znear, zfar);
01521 glMatrixMode(GL_MODELVIEW);
01522 glCullFace(GL_BACK);
01523 }
01524 }