Turned DrawingEffect into a proper bitset, used to be a mix of enum/bitset before...
[supertux.git] / src / video / sdl / sdl_painter.cpp
index b47c7f1..6ba8f42 100644 (file)
 
 #include "SDL.h"
 
+#include "util/log.hpp"
 #include "video/drawing_request.hpp"
 #include "video/sdl/sdl_texture.hpp"
 
+namespace {
+
+SDL_BlendMode blend2sdl(const Blend& blend)
+{
+  if (blend.sfactor == GL_ONE &&
+      blend.dfactor == GL_ZERO)
+  {
+    return SDL_BLENDMODE_NONE;
+  }
+  else if (blend.sfactor == GL_SRC_ALPHA &&
+           blend.dfactor == GL_ONE_MINUS_SRC_ALPHA)
+  {
+    return SDL_BLENDMODE_BLEND;
+  }
+  else if (blend.sfactor == GL_SRC_ALPHA &&
+           blend.dfactor == GL_ONE)
+  {
+    return SDL_BLENDMODE_ADD;
+  }
+  else if (blend.sfactor == GL_DST_COLOR &&
+           blend.dfactor == GL_ZERO)
+  {
+    return SDL_BLENDMODE_MOD;
+  }
+  else
+  {
+    log_warning << "unknown blend mode combinations: sfactor=" << blend.sfactor << " dfactor=" << blend.dfactor << std::endl;
+    return SDL_BLENDMODE_BLEND;
+  }
+}
+
+} // namespace
+
 void
 SDLPainter::draw_surface(SDL_Renderer* renderer, const DrawingRequest& request)
 {
-  //FIXME: support parameters request.angle, request.blend
   const Surface* surface = (const Surface*) request.request_data;
   boost::shared_ptr<SDLTexture> sdltexture = boost::dynamic_pointer_cast<SDLTexture>(surface->get_texture());
 
@@ -40,35 +73,26 @@ SDLPainter::draw_surface(SDL_Renderer* renderer, const DrawingRequest& request)
   Uint8 a = static_cast<Uint8>(request.color.alpha * request.alpha * 255);
   SDL_SetTextureColorMod(sdltexture->get_texture(), r, g, b);
   SDL_SetTextureAlphaMod(sdltexture->get_texture(), a);
+  SDL_SetTextureBlendMode(sdltexture->get_texture(), blend2sdl(request.blend));
 
-  if (surface->get_flipx())
+  SDL_RendererFlip flip = SDL_FLIP_NONE;
+  if (surface->get_flipx() || request.drawing_effect & HORIZONTAL_FLIP)
   {
-    SDL_RenderCopyEx(renderer, sdltexture->get_texture(), NULL, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
+    flip = static_cast<SDL_RendererFlip>(flip | SDL_FLIP_HORIZONTAL);
   }
-  else
+
+  if (request.drawing_effect & VERTICAL_FLIP)
   {
-    switch(request.drawing_effect)
-    {
-      case VERTICAL_FLIP:
-        SDL_RenderCopyEx(renderer, sdltexture->get_texture(), NULL, &dst_rect, 0, NULL, SDL_FLIP_VERTICAL);
-        break;
-
-      case HORIZONTAL_FLIP:
-        SDL_RenderCopyEx(renderer, sdltexture->get_texture(), NULL, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
-        break;
-
-      default:
-      case NO_EFFECT:
-        SDL_RenderCopy(renderer, sdltexture->get_texture(), NULL, &dst_rect);
-        break;
-    }
+    flip = static_cast<SDL_RendererFlip>(flip | SDL_FLIP_VERTICAL);
   }
+
+  SDL_RenderCopyEx(renderer, sdltexture->get_texture(), NULL, &dst_rect, request.angle, NULL, flip);
 }
 
 void
 SDLPainter::draw_surface_part(SDL_Renderer* renderer, const DrawingRequest& request)
 {
-  //FIXME: support parameters request.angle, request.blend
+  //FIXME: support parameters request.blend
   const SurfacePartRequest* surface = (const SurfacePartRequest*) request.request_data;
   const SurfacePartRequest* surfacepartrequest = (SurfacePartRequest*) request.request_data;
 
@@ -92,42 +116,30 @@ SDLPainter::draw_surface_part(SDL_Renderer* renderer, const DrawingRequest& requ
   Uint8 a = static_cast<Uint8>(request.color.alpha * request.alpha * 255);
   SDL_SetTextureColorMod(sdltexture->get_texture(), r, g, b);
   SDL_SetTextureAlphaMod(sdltexture->get_texture(), a);
+  SDL_SetTextureBlendMode(sdltexture->get_texture(), blend2sdl(request.blend));
 
-  if (surface->surface->get_flipx())
+  SDL_RendererFlip flip = SDL_FLIP_NONE;
+  if (surface->surface->get_flipx() || request.drawing_effect & HORIZONTAL_FLIP)
   {
-    SDL_RenderCopyEx(renderer, sdltexture->get_texture(), &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
+    flip = static_cast<SDL_RendererFlip>(flip | SDL_FLIP_HORIZONTAL);
   }
-  else
+
+  if (request.drawing_effect & VERTICAL_FLIP)
   {
-    switch(request.drawing_effect)
-    {
-      case VERTICAL_FLIP:
-        SDL_RenderCopyEx(renderer, sdltexture->get_texture(), &src_rect, &dst_rect, 0, NULL, SDL_FLIP_VERTICAL);
-        break;
-
-      case HORIZONTAL_FLIP:
-        SDL_RenderCopyEx(renderer, sdltexture->get_texture(), &src_rect, &dst_rect, 0, NULL, SDL_FLIP_HORIZONTAL);
-        break;
-
-      default:
-      case NO_EFFECT:
-        SDL_RenderCopy(renderer, sdltexture->get_texture(), &src_rect, &dst_rect);
-        break;
-    }
+    flip = static_cast<SDL_RendererFlip>(flip | SDL_FLIP_VERTICAL);
   }
+
+  SDL_RenderCopyEx(renderer, sdltexture->get_texture(), &src_rect, &dst_rect, request.angle, NULL, flip);
 }
 
 void
 SDLPainter::draw_gradient(SDL_Renderer* renderer, const DrawingRequest& request)
 {
-  const GradientRequest* gradientrequest 
+  const GradientRequest* gradientrequest
     = (GradientRequest*) request.request_data;
   const Color& top = gradientrequest->top;
   const Color& bottom = gradientrequest->bottom;
 
-  SDL_Rect viewport;
-  SDL_RenderGetViewport(renderer, &viewport);
-
   // calculate the maximum number of steps needed for the gradient
   int n = static_cast<int>(std::max(std::max(fabsf(top.red - bottom.red),
                                              fabsf(top.green - bottom.green)),
@@ -137,9 +149,9 @@ SDLPainter::draw_gradient(SDL_Renderer* renderer, const DrawingRequest& request)
   {
     SDL_Rect rect;
     rect.x = 0;
-    rect.y = viewport.h * i / n;
-    rect.w = viewport.w;
-    rect.h = (viewport.h * (i+1) / n) - rect.y;
+    rect.y = SCREEN_HEIGHT * i / n;
+    rect.w = SCREEN_WIDTH;
+    rect.h = (SCREEN_HEIGHT * (i+1) / n) - rect.y;
 
     float p = static_cast<float>(i+1) / static_cast<float>(n);
     Uint8 r = static_cast<Uint8>(((1.0f - p) * top.red + p * bottom.red)  * 255);
@@ -234,9 +246,6 @@ void
 SDLPainter::draw_inverse_ellipse(SDL_Renderer* renderer, const DrawingRequest& request)
 {
   const InverseEllipseRequest* ellipse = (InverseEllipseRequest*)request.request_data;
-  
-  SDL_Rect viewport;
-  SDL_RenderGetViewport(renderer, &viewport);
 
   float x = request.pos.x;
   float w = ellipse->size.x;
@@ -249,7 +258,7 @@ SDLPainter::draw_inverse_ellipse(SDL_Renderer* renderer, const DrawingRequest& r
   int slices = std::min(static_cast<int>(ellipse->size.y), max_slices);
   for(int i = 0; i < slices; ++i)
   {
-    float p = ((static_cast<float>(i) + 0.5f) / static_cast<float>(slices)) * 2.0f - 1.0f; 
+    float p = ((static_cast<float>(i) + 0.5f) / static_cast<float>(slices)) * 2.0f - 1.0f;
     int xoff = static_cast<int>(sqrtf(1.0f - p*p) * w / 2);
 
     SDL_Rect& left  = rects[2*i+0];
@@ -262,7 +271,7 @@ SDLPainter::draw_inverse_ellipse(SDL_Renderer* renderer, const DrawingRequest& r
 
     right.x = x + xoff;
     right.y = left.y;
-    right.w = viewport.w - right.x;
+    right.w = SCREEN_WIDTH - right.x;
     right.h = left.h;
   }
 
@@ -271,13 +280,13 @@ SDLPainter::draw_inverse_ellipse(SDL_Renderer* renderer, const DrawingRequest& r
 
   top_rect.x = 0;
   top_rect.y = 0;
-  top_rect.w = viewport.w;
+  top_rect.w = SCREEN_WIDTH;
   top_rect.h = top;
 
   bottom_rect.x = 0;
   bottom_rect.y = top + h;
-  bottom_rect.w = viewport.w;
-  bottom_rect.h = viewport.h - bottom_rect.y;
+  bottom_rect.w = SCREEN_WIDTH;
+  bottom_rect.h = SCREEN_HEIGHT - bottom_rect.y;
 
   Uint8 r = static_cast<Uint8>(ellipse->color.red * 255);
   Uint8 g = static_cast<Uint8>(ellipse->color.green * 255);