29#include <guichan/exception.hpp>
35 int rendererFlags = 0;
37 rendererFlags |= SDL_RENDERER_PRESENTVSYNC;
39 SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, rendererFlags);
42 Log::critical(
strprintf(
"Failed to create renderer: %s",
47 return std::make_unique<SDLGraphics>(window, renderer);
58 SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
60 if (
const char *driver = SDL_GetCurrentVideoDriver())
61 Log::info(
"Using video driver: %s", driver);
63 Log::info(
"Using video driver: not initialized");
65 SDL_RendererInfo info;
67 if (SDL_GetRendererInfo(renderer, &info) == 0) {
68 Log::info(
"Using renderer: %s", info.name);
70 Log::info(
"The renderer is a software fallback: %s",
71 (info.flags & SDL_RENDERER_SOFTWARE) ?
"yes" :
"no");
72 Log::info(
"The renderer is hardware accelerated: %s",
73 (info.flags & SDL_RENDERER_ACCELERATED) ?
"yes" :
"no");
75 (info.flags & SDL_RENDERER_PRESENTVSYNC) ?
"on" :
"off");
76 Log::info(
"Renderer supports rendering to texture: %s",
77 (info.flags & SDL_RENDERER_TARGETTEXTURE) ?
"yes" :
"no");
79 info.max_texture_width, info.max_texture_height);
90#if SDL_VERSION_ATLEAST(2, 0, 18)
91 SDL_RenderSetVSync(
mRenderer, sync ? SDL_TRUE : SDL_FALSE);
99 float displayScaleX = windowWidth > 0 ?
static_cast<float>(
mWidth) / windowWidth : 1.0f;
100 float displayScaleY = windowHeight > 0 ?
static_cast<float>(
mHeight) / windowHeight : 1.0f;
102 float scaleX = scale * displayScaleX;
103 float scaleY = scale * displayScaleY;
109 SDL_RenderSetScale(
mRenderer, scaleX, scaleY);
115 int width,
int height,
116 int desiredWidth,
int desiredHeight,
123 dstX += mClipStack.top().xOffset;
124 dstY += mClipStack.top().yOffset;
131 dstRect.x = dstX; dstRect.y = dstY;
132 srcRect.x = srcX; srcRect.y = srcY;
135 dstRect.w = desiredWidth;
136 dstRect.h = desiredHeight;
142#if SDL_VERSION_ATLEAST(2, 0, 10)
145 float dstX,
float dstY,
146 int width,
int height,
147 float desiredWidth,
float desiredHeight,
154 dstX += mClipStack.top().xOffset;
155 dstY += mClipStack.top().yOffset;
162 dstRect.x = dstX; dstRect.y = dstY;
163 srcRect.x = srcX; srcRect.y = srcY;
166 dstRect.w = desiredWidth;
167 dstRect.h = desiredHeight;
186 if (scaledHeight <= 0 || scaledWidth <= 0)
192 srcRect.x = image->
mBounds.x + srcX;
193 srcRect.y = image->
mBounds.y + srcY;
195 for (
int py = 0; py < dstH; py += scaledHeight)
198 dstRect.h = (py + scaledHeight >= dstH) ? dstH - py : scaledHeight;
199 dstRect.y = dstY + py + mClipStack.top().yOffset;
201 for (
int px = 0; px < dstW; px += scaledWidth)
203 dstRect.x = dstX + px + mClipStack.top().xOffset;
204 dstRect.w = (px + scaledWidth >= dstW) ? dstW - px : scaledWidth;
206 srcRect.w = srcW * dstRect.w / scaledWidth;
207 srcRect.h = srcH * dstRect.h / scaledHeight;
221 float &logicalX,
float &logicalY)
const
223#if SDL_VERSION_ATLEAST(2, 0, 18)
224 SDL_RenderWindowToLogical(
mRenderer, windowX, windowY, &logicalX, &logicalY);
228 SDL_RenderGetScale(
mRenderer, &scaleX, &scaleY);
229 logicalX = windowX / scaleX;
230 logicalY = windowY / scaleY;
236#if SDL_BYTEORDER == SDL_BIG_ENDIAN
237 int rmask = 0xff000000;
238 int gmask = 0x00ff0000;
239 int bmask = 0x0000ff00;
241 int rmask = 0x000000ff;
242 int gmask = 0x0000ff00;
243 int bmask = 0x00ff0000;
245 int amask = 0x00000000;
248 if (SDL_GetRendererOutputSize(
mRenderer, &width, &height) != 0)
251 SDL_Surface *screenshot = SDL_CreateRGBSurface(0, width, height, 24,
252 rmask, gmask, bmask, amask);
254 if (SDL_RenderReadPixels(
mRenderer,
nullptr,
255 screenshot->format->format,
257 screenshot->pitch) != 0)
259 SDL_FreeSurface(screenshot);
260 screenshot =
nullptr;
270 SDL_RenderSetClipRect(
mRenderer,
nullptr);
274 const gcn::Rectangle &clipRect =
mClipRects.top();
275 const SDL_Rect rect = {
287 if (mClipStack.empty())
289 throw GCN_EXCEPTION(
"Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
292 const gcn::ClipRectangle &top = mClipStack.top();
297 if (!top.isPointInRect(x, y))
310 if (mClipStack.empty())
312 throw GCN_EXCEPTION(
"Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
315 const gcn::ClipRectangle &top = mClipStack.top();
327 SDL_RenderDrawLine(
mRenderer, x1, y1, x2, y2);
332 if (mClipStack.empty())
334 throw GCN_EXCEPTION(
"Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
337 const gcn::ClipRectangle &top = mClipStack.top();
340 rect.x = rectangle.x + top.xOffset;
341 rect.y = rectangle.y + top.yOffset;
342 rect.w = rectangle.width;
343 rect.h = rectangle.height;
355 if (mClipStack.empty())
357 throw GCN_EXCEPTION(
"Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
360 const gcn::ClipRectangle &top = mClipStack.top();
362 gcn::Rectangle area = rectangle;
363 area.x += top.xOffset;
364 area.y += top.yOffset;
366 if(!area.isIntersecting(top))
375 rect.h = area.height;
387 SDL_Color color = { 255, 255, 255, 255 };
397 SDL_Texture *texture = image->
mTexture;
398 SDL_SetTextureColorMod(texture, color.r, color.g, color.b);
399 SDL_SetTextureAlphaMod(texture, color.a);
std::stack< gcn::Rectangle > mClipRects
virtual bool drawRescaledImageF(const Image *image, int srcX, int srcY, float dstX, float dstY, int width, int height, float desiredWidth, float desiredHeight, bool useColor=false)
Draws a rescaled version of the image.
Defines a class for loading and storing images.
float getAlpha() const
Returns the alpha value of this image.
static void setRenderer(SDL_Renderer *renderer)
static std::unique_ptr< Graphics > create(SDL_Window *window, const VideoSettings &settings)
SDL_Surface * getScreenshot() override
Takes a screenshot and returns it as SDL surface.
SDLGraphics(SDL_Window *window, SDL_Renderer *renderer)
void updateClipRect() override
void drawRescaledImagePattern(const Image *image, int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH, int scaledWidth, int scaledHeight) override
Draw a pattern based on a rescaled version of the given image.
void drawPoint(int x, int y) override
void updateScreen() override
Updates the screen.
void setVSync(bool sync) override
Sets whether vertical refresh syncing is enabled.
void updateSize(int windowWidth, int windowHeight, float scale) override
Called when the window size or scale has changed.
bool drawRescaledImage(const Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height, int desiredWidth, int desiredHeight, bool useColor) override
Draws a rescaled version of the image.
void setColorAlphaMod(const Image *image, bool useColor) const
void windowToLogical(int windowX, int windowY, float &logicalX, float &logicalY) const override
Converts a window coordinate to a logical coordinate.
void drawRectangle(const gcn::Rectangle &rectangle) override
void drawLine(int x1, int y1, int x2, int y2) override
void fillRectangle(const gcn::Rectangle &rectangle) override
void info(const char *log_text,...) LOG_PRINTF_ATTR
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.