Prevent crash on exit.
[supertux.git] / src / video / gl_lightmap.cpp
index 6649a0e..9287bec 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "glutil.hpp"
 #include "gl_lightmap.hpp"
+#include "gl_surface_data.hpp"
 #include "drawing_context.hpp"
 #include "drawing_request.hpp"
 #include "renderer.hpp"
 #include "gl_texture.hpp"
 #include "texture_manager.hpp"
 #include "obstack/obstackpp.hpp"
-#define LIGHTMAP_DIV 5
 
 namespace
 {
-  inline void intern_draw(float left, float top, float right, float bottom,
-                                  float uv_left, float uv_top,
-                                  float uv_right, float uv_bottom,
-                                  float angle, float alpha,
-                                  const Color& color,
-                                  const Blend& blend,
-                                  DrawingEffect effect)
-  {
-    if(effect & HORIZONTAL_FLIP)
-      std::swap(uv_left, uv_right);
-    if(effect & VERTICAL_FLIP) {
-      std::swap(uv_top, uv_bottom);
-    }
 
+inline void intern_draw(float left, float top, float right, float bottom,
+                        float uv_left, float uv_top,
+                        float uv_right, float uv_bottom,
+                        float angle, float alpha,
+                        const Color& color,
+                        const Blend& blend,
+                        DrawingEffect effect)
+{
+  if(effect & HORIZONTAL_FLIP)
+    std::swap(uv_left, uv_right);
+  if(effect & VERTICAL_FLIP) 
+    std::swap(uv_top, uv_bottom);
+
+  // unrotated blit
+  glBlendFunc(blend.sfactor, blend.dfactor);
+  glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
+  if (angle == 0.0f) {
+    float vertices[] = {
+      left, top,
+      right, top,
+      right, bottom,
+      left, bottom,
+    };
+    glVertexPointer(2, GL_FLOAT, 0, vertices);
+
+    float uvs[] = {
+      uv_left, uv_top,
+      uv_right, uv_top,
+      uv_right, uv_bottom,
+      uv_left, uv_bottom,
+    };
+    glTexCoordPointer(2, GL_FLOAT, 0, uvs);
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+  } else {
+    // rotated blit
     float center_x = (left + right) / 2;
     float center_y = (top + bottom) / 2;
 
@@ -72,30 +97,30 @@ namespace
     top    -= center_y;
     bottom -= center_y;
 
-    glBlendFunc(blend.sfactor, blend.dfactor);
-    glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
-    glBegin(GL_QUADS);
-    glTexCoord2f(uv_left, uv_top);
-    glVertex2f(left*ca - top*sa + center_x,
-               left*sa + top*ca + center_y);
-
-    glTexCoord2f(uv_right, uv_top);
-    glVertex2f(right*ca - top*sa + center_x,
-               right*sa + top*ca + center_y);
-
-    glTexCoord2f(uv_right, uv_bottom);
-    glVertex2f(right*ca - bottom*sa + center_x,
-               right*sa + bottom*ca + center_y);
+    float vertices[] = {
+        left*ca - top*sa + center_x, left*sa + top*ca + center_y,
+        right*ca - top*sa + center_x, right*sa + top*ca + center_y,
+        right*ca - bottom*sa + center_x, right*sa + bottom*ca + center_y,
+        left*ca - bottom*sa + center_x, left*sa + bottom*ca + center_y
+    };
+    glVertexPointer(2, GL_FLOAT, 0, vertices);
+
+    float uvs[] = {
+      uv_left, uv_top,
+      uv_right, uv_top,
+      uv_right, uv_bottom,
+      uv_left, uv_bottom,
+    };
+    glTexCoordPointer(2, GL_FLOAT, 0, uvs);
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+  }
 
-    glTexCoord2f(uv_left, uv_bottom);
-    glVertex2f(left*ca - bottom*sa + center_x,
-               left*sa + bottom*ca + center_y);
-    glEnd();
+  // FIXME: find a better way to restore the blend mode
+  glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
 
-    // FIXME: find a better way to restore the blend mode
-    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-  }
 }
 
 namespace GL
@@ -127,7 +152,9 @@ namespace GL
 
   Lightmap::~Lightmap()
   {
-    texture_manager->remove_texture(lightmap);
+    if(texture_manager){
+      texture_manager->remove_texture(lightmap);
+    }
     delete lightmap;
   }
 
@@ -137,7 +164,11 @@ namespace GL
     glViewport(0, screen->h - lightmap_height, lightmap_width, lightmap_height);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
+#ifdef GL_VERSION_ES_CM_1_0
+    glOrthof(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
+#else
     glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
+#endif
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
 
@@ -155,7 +186,11 @@ namespace GL
     glViewport(0, 0, screen->w, screen->h);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
+#ifdef GL_VERSION_ES_CM_1_0
+    glOrthof(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
+#else
     glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
+#endif
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     glEnable(GL_BLEND);
@@ -171,21 +206,24 @@ namespace GL
     glBlendFunc(GL_DST_COLOR, GL_ZERO);
 
     glBindTexture(GL_TEXTURE_2D, texture->get_handle());
-    glBegin(GL_QUADS);
 
-    glTexCoord2f(0, lightmap_uv_bottom);
-    glVertex2f(0, 0);
+    float vertices[] = {
+      0, 0,
+      SCREEN_WIDTH, 0,
+      SCREEN_WIDTH, SCREEN_HEIGHT,
+      0, SCREEN_HEIGHT
+    };
+    glVertexPointer(2, GL_FLOAT, 0, vertices);
 
-    glTexCoord2f(lightmap_uv_right, lightmap_uv_bottom);
-    glVertex2f(SCREEN_WIDTH, 0);
+    float uvs[] = {
+      0,                 lightmap_uv_bottom,
+      lightmap_uv_right, lightmap_uv_bottom,
+      lightmap_uv_right, 0,
+      0, 0
+    };
+    glTexCoordPointer(2, GL_FLOAT, 0, uvs);
 
-    glTexCoord2f(lightmap_uv_right, 0);
-    glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
-
-    glTexCoord2f(0, 0);
-    glVertex2f(0, SCREEN_HEIGHT);
-
-    glEnd();
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   }
@@ -195,14 +233,16 @@ namespace GL
   {
     const Surface* surface = (const Surface*) request.request_data;
     GL::Texture *gltexture = dynamic_cast<GL::Texture *>(surface->get_texture());
+    GL::SurfaceData *surface_data = reinterpret_cast<GL::SurfaceData *>(surface->get_surface_data());
+
     glBindTexture(GL_TEXTURE_2D, gltexture->get_handle());
     intern_draw(request.pos.x, request.pos.y,
                 request.pos.x + surface->get_width(),
                 request.pos.y + surface->get_height(),
-                surface->get_uv_left(),
-                surface->get_uv_top(),
-                surface->get_uv_right(),
-                surface->get_uv_bottom(),
+                surface_data->get_uv_left(),
+                surface_data->get_uv_top(),
+                surface_data->get_uv_right(),
+                surface_data->get_uv_bottom(),
                 request.angle,
                 request.alpha,
                 request.color,
@@ -217,14 +257,15 @@ namespace GL
       = (SurfacePartRequest*) request.request_data;
     const Surface *surface = surfacepartrequest->surface;
     GL::Texture *gltexture = dynamic_cast<GL::Texture *>(surface->get_texture());
+    GL::SurfaceData *surface_data = reinterpret_cast<GL::SurfaceData *>(surface->get_surface_data());
 
-    float uv_width = surface->get_uv_right() - surface->get_uv_left();
-    float uv_height = surface->get_uv_bottom() - surface->get_uv_top();
+    float uv_width = surface_data->get_uv_right() - surface_data->get_uv_left();
+    float uv_height = surface_data->get_uv_bottom() - surface_data->get_uv_top();
 
-    float uv_left = surface->get_uv_left() + (uv_width * surfacepartrequest->source.x) / surface->get_width();
-    float uv_top = surface->get_uv_top() + (uv_height * surfacepartrequest->source.y) / surface->get_height();
-    float uv_right = surface->get_uv_left() + (uv_width * (surfacepartrequest->source.x + surfacepartrequest->size.x)) / surface->get_width();
-    float uv_bottom = surface->get_uv_top() + (uv_height * (surfacepartrequest->source.y + surfacepartrequest->size.y)) / surface->get_height();
+    float uv_left = surface_data->get_uv_left() + (uv_width * surfacepartrequest->source.x) / surface->get_width();
+    float uv_top = surface_data->get_uv_top() + (uv_height * surfacepartrequest->source.y) / surface->get_height();
+    float uv_right = surface_data->get_uv_left() + (uv_width * (surfacepartrequest->source.x + surfacepartrequest->size.x)) / surface->get_width();
+    float uv_bottom = surface_data->get_uv_top() + (uv_height * (surfacepartrequest->source.y + surfacepartrequest->size.y)) / surface->get_height();
 
     glBindTexture(GL_TEXTURE_2D, gltexture->get_handle());
     intern_draw(request.pos.x, request.pos.y,
@@ -250,28 +291,35 @@ namespace GL
     const Color& bottom = gradientrequest->bottom;
 
     glDisable(GL_TEXTURE_2D);
-    glBegin(GL_QUADS);
-    glColor4f(top.red, top.green, top.blue, top.alpha);
-    glVertex2f(0, 0);
-    glVertex2f(SCREEN_WIDTH, 0);
-    glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
-    glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
-    glVertex2f(0, SCREEN_HEIGHT);
-    glEnd();
+    glDisable(GL_TEXTURE_COORD_ARRAY);
+    glEnable(GL_COLOR_ARRAY);
+
+    float vertices[] = {
+      0, 0,
+      SCREEN_WIDTH, 0,
+      SCREEN_WIDTH, SCREEN_HEIGHT,
+      0, SCREEN_HEIGHT
+    };
+    glVertexPointer(2, GL_FLOAT, 0, vertices);
+
+    float colors[] = {
+      top.red, top.green, top.blue, top.alpha,
+      top.red, top.green, top.blue, top.alpha,
+      bottom.red, bottom.green, bottom.blue, bottom.alpha,
+      bottom.red, bottom.green, bottom.blue, bottom.alpha,
+    };
+    glColorPointer(4, GL_FLOAT, 0, colors);
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+    glDisable(GL_COLOR_ARRAY);
+    glEnable(GL_TEXTURE_COORD_ARRAY);
+
     glEnable(GL_TEXTURE_2D);
     glColor4f(1, 1, 1, 1);
   }
 
   void
-  Lightmap::draw_text(const DrawingRequest& /*request*/)
-  {
-    //const TextRequest* textrequest = (TextRequest*) request.request_data;
-
-    //textrequest->font->draw(textrequest->text, request.pos,
-    //    textrequest->alignment, request.drawing_effect, request.alpha);
-  }
-
-  void
   Lightmap::draw_filled_rect(const DrawingRequest& request)
   {
     const FillRectRequest* fillrectrequest
@@ -285,13 +333,19 @@ namespace GL
     glDisable(GL_TEXTURE_2D);
     glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
               fillrectrequest->color.blue, fillrectrequest->color.alpha);
+    glDisable(GL_TEXTURE_COORD_ARRAY);
+
+    float vertices[] = {
+      x,   y,
+      x+w, y,
+      x+w, y+h,
+      x,   y+h
+    };
+    glVertexPointer(2, GL_FLOAT, 0, vertices);
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
-    glBegin(GL_QUADS);
-    glVertex2f(x, y);
-    glVertex2f(x+w, y);
-    glVertex2f(x+w, y+h);
-    glVertex2f(x, y+h);
-    glEnd();
+    glEnable(GL_TEXTURE_COORD_ARRAY);
     glEnable(GL_TEXTURE_2D);
     glColor4f(1, 1, 1, 1);
   }
@@ -310,7 +364,6 @@ namespace GL
     float posY = screen->h - request.pos.y * lightmap_height / SCREEN_HEIGHT;
     glReadPixels((GLint) posX, (GLint) posY , 1, 1, GL_RGB, GL_FLOAT, pixels);
     *(getlightrequest->color_ptr) = Color( pixels[0], pixels[1], pixels[2]);
-    //printf("get_light %f/%f =>%f/%f r%f g%f b%f\n", request.pos.x, request.pos.y, posX, posY, pixels[0], pixels[1], pixels[2]);
   }
 }