#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());
+ const Surface* surface = static_cast<const SurfaceRequest*>(request.request_data)->surface;
+ std::shared_ptr<SDLTexture> sdltexture = std::dynamic_pointer_cast<SDLTexture>(surface->get_texture());
SDL_Rect dst_rect;
dst_rect.x = request.pos.x;
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
- const SurfacePartRequest* surface = (const SurfacePartRequest*) request.request_data;
- const SurfacePartRequest* surfacepartrequest = (SurfacePartRequest*) request.request_data;
+ //FIXME: support parameters request.blend
+ const SurfacePartRequest* surface = static_cast<const SurfacePartRequest*>(request.request_data);
+ const SurfacePartRequest* surfacepartrequest = static_cast<SurfacePartRequest*>(request.request_data);
- boost::shared_ptr<SDLTexture> sdltexture = boost::dynamic_pointer_cast<SDLTexture>(surface->surface->get_texture());
+ std::shared_ptr<SDLTexture> sdltexture = std::dynamic_pointer_cast<SDLTexture>(surface->surface->get_texture());
SDL_Rect src_rect;
- src_rect.x = surfacepartrequest->source.x;
- src_rect.y = surfacepartrequest->source.y;
- src_rect.w = surfacepartrequest->size.x;
- src_rect.h = surfacepartrequest->size.y;
+ src_rect.x = surfacepartrequest->srcrect.p1.x;
+ src_rect.y = surfacepartrequest->srcrect.p1.y;
+ src_rect.w = surfacepartrequest->srcrect.get_width();
+ src_rect.h = surfacepartrequest->srcrect.get_height();
SDL_Rect dst_rect;
dst_rect.x = request.pos.x;
dst_rect.y = request.pos.y;
- dst_rect.w = surfacepartrequest->size.x;
- dst_rect.h = surfacepartrequest->size.y;
+ dst_rect.w = surfacepartrequest->dstsize.width;
+ dst_rect.h = surfacepartrequest->dstsize.height;
Uint8 r = static_cast<Uint8>(request.color.red * 255);
Uint8 g = static_cast<Uint8>(request.color.green * 255);
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
- = (GradientRequest*) request.request_data;
+ const GradientRequest* gradientrequest
+ = static_cast<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)),
std::max(fabsf(top.blue - bottom.blue),
fabsf(top.alpha - bottom.alpha))) * 255);
+ n = std::max(n, 1);
for(int i = 0; i < n; ++i)
{
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);
SDLPainter::draw_filled_rect(SDL_Renderer* renderer, const DrawingRequest& request)
{
const FillRectRequest* fillrectrequest
- = (FillRectRequest*) request.request_data;
+ = static_cast<FillRectRequest*>(request.request_data);
SDL_Rect rect;
rect.x = request.pos.x;
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);
+ const InverseEllipseRequest* ellipse = static_cast<InverseEllipseRequest*>(request.request_data);
float x = request.pos.x;
float w = ellipse->size.x;
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];
right.x = x + xoff;
right.y = left.y;
- right.w = viewport.w - right.x;
+ right.w = SCREEN_WIDTH - right.x;
right.h = left.h;
}
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);