summaryrefslogtreecommitdiff
path: root/src/graphics.cpp
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-01-25 15:41:57 +0100
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-01-25 15:41:57 +0100
commit2c51c98625b225cecfb9628c30d62d4e30f7e3e1 (patch)
tree5f8f85a40785439b6a9ea249a75e81e26d1b44f1 /src/graphics.cpp
parent8fdbae08d7f269c72889f89b56493071a2279350 (diff)
downloadmana-2c51c98625b225cecfb9628c30d62d4e30f7e3e1.tar.gz
mana-2c51c98625b225cecfb9628c30d62d4e30f7e3e1.tar.bz2
mana-2c51c98625b225cecfb9628c30d62d4e30f7e3e1.tar.xz
mana-2c51c98625b225cecfb9628c30d62d4e30f7e3e1.zip
Ported to SDL2
Diffstat (limited to 'src/graphics.cpp')
-rw-r--r--src/graphics.cpp367
1 files changed, 214 insertions, 153 deletions
diff --git a/src/graphics.cpp b/src/graphics.cpp
index ac3735f5..b4c65b0a 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -19,8 +19,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <cassert>
-
#include "graphics.h"
#include "log.h"
@@ -28,103 +26,95 @@
#include "utils/gettext.h"
-#include <SDL_gfxBlitFunc.h>
+#include <guichan/exception.hpp>
-Graphics::Graphics():
- mWidth(0),
- mHeight(0),
- mBpp(0),
- mFullscreen(false),
- mHWAccel(false),
- mBlitMode(BLIT_NORMAL)
+Graphics::~Graphics()
{
+ _endDraw();
}
-Graphics::~Graphics()
+void Graphics::setTarget(SDL_Window *target)
{
_endDraw();
+
+ mTarget = target;
+
+ if (mTarget)
+ _beginDraw();
}
-bool Graphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel)
+bool Graphics::setVideoMode(int w, int h, bool fs)
{
logger->log("Setting video mode %dx%d %s",
w, h, fs ? "fullscreen" : "windowed");
- logger->log("Bits per pixel: %d", bpp);
-
- int displayFlags = SDL_ANYFORMAT;
+ int windowFlags = SDL_WINDOW_ALLOW_HIGHDPI;
if (fs)
- displayFlags |= SDL_FULLSCREEN;
+ windowFlags |= SDL_WINDOW_FULLSCREEN;
else
- displayFlags |= SDL_RESIZABLE;
+ windowFlags |= SDL_WINDOW_RESIZABLE;
- if (hwaccel)
- displayFlags |= SDL_HWSURFACE | SDL_DOUBLEBUF;
- else
- displayFlags |= SDL_SWSURFACE;
+ // TODO_SDL2: Support SDL_WINDOW_FULLSCREEN_DESKTOP
- setTarget(SDL_SetVideoMode(w, h, bpp, displayFlags));
+ SDL_Window *window = nullptr;
+ SDL_Renderer *renderer = nullptr;
+ SDL_CreateWindowAndRenderer(w, h, windowFlags, &window, &renderer);
- if (!mTarget)
+ if (!window)
return false;
+ SDL_SetWindowMinimumSize(window, 640, 480);
+ SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
+
+ setTarget(window);
+
+ mRenderer = renderer;
mWidth = w;
mHeight = h;
- mBpp = bpp;
mFullscreen = fs;
- mHWAccel = hwaccel;
- char videoDriverName[64];
-
- if (SDL_VideoDriverName(videoDriverName, 64))
- logger->log("Using video driver: %s", videoDriverName);
+ if (const char *driver = SDL_GetCurrentVideoDriver())
+ logger->log("Using video driver: %s", driver);
else
- logger->log("Using video driver: unknown");
-
- const SDL_VideoInfo *vi = SDL_GetVideoInfo();
-
- logger->log("Possible to create hardware surfaces: %s",
- vi->hw_available ? "yes" : "no");
- logger->log("Window manager available: %s",
- vi->wm_available ? "yes" : "no");
- logger->log("Accelerated hardware to hardware blits: %s",
- vi->blit_hw ? "yes" : "no");
- logger->log("Accelerated hardware to hardware colorkey blits: %s",
- vi->blit_hw_CC ? "yes" : "no");
- logger->log("Accelerated hardware to hardware alpha blits: %s",
- vi->blit_hw_A ? "yes" : "no");
- logger->log("Accelerated software to hardware blits: %s",
- vi->blit_sw ? "yes" : "no");
- logger->log("Accelerated software to hardware colorkey blits: %s",
- vi->blit_sw_CC ? "yes" : "no");
- logger->log("Accelerated software to hardware alpha blits: %s",
- vi->blit_sw_A ? "yes" : "no");
- logger->log("Accelerated color fills: %s",
- vi->blit_fill ? "yes" : "no");
- logger->log("Available video memory: %d", vi->video_mem);
+ logger->log("Using video driver: not initialized");
+
+ SDL_RendererInfo info;
+
+ if (SDL_GetRendererInfo(mRenderer, &info) == 0) {
+ logger->log("Using renderer: %s", info.name);
+
+ logger->log("The renderer is a software fallback: %s",
+ (info.flags & SDL_RENDERER_SOFTWARE) ? "yes" : "no");
+ logger->log("The renderer is hardware accelerated: %s",
+ (info.flags & SDL_RENDERER_ACCELERATED) ? "yes" : "no");
+ logger->log("Vsync: %s",
+ (info.flags & SDL_RENDERER_PRESENTVSYNC) ? "on" : "off");
+ logger->log("Renderer supports rendering to texture: %s",
+ (info.flags & SDL_RENDERER_TARGETTEXTURE) ? "yes" : "no");
+ logger->log("Max texture size: %dx%d",
+ info.max_texture_width, info.max_texture_height);
+ }
return true;
}
-bool Graphics::changeVideoMode(int w, int h, int bpp, bool fs, bool hwaccel)
+bool Graphics::changeVideoMode(int w, int h, bool fs)
{
// Just return success if we're already in this mode
if (mWidth == w &&
mHeight == h &&
- mBpp == bpp &&
- mFullscreen == fs &&
- mHWAccel == hwaccel)
+ mFullscreen == fs)
return true;
_endDraw();
- bool success = setVideoMode(w, h, bpp, fs, hwaccel);
+ bool success = setVideoMode(w, h, fs);
// If it didn't work, try to restore the previous mode. If that doesn't
// work either, we're in big trouble and bail out.
if (!success) {
- if (!setVideoMode(mWidth, mHeight, mBpp, mFullscreen, mHWAccel)) {
+ if (!setVideoMode(mWidth, mHeight, mFullscreen)) {
logger->error(_("Failed to change video mode and couldn't "
"switch back to the previous mode!"));
}
@@ -135,6 +125,12 @@ bool Graphics::changeVideoMode(int w, int h, int bpp, bool fs, bool hwaccel)
return success;
}
+void Graphics::videoResized(int w, int h)
+{
+ mWidth = w;
+ mHeight = h;
+}
+
int Graphics::getWidth() const
{
return mWidth;
@@ -147,10 +143,10 @@ int Graphics::getHeight() const
bool Graphics::drawImage(Image *image, int x, int y)
{
- if (image)
- return drawImage(image, 0, 0, x, y, image->mBounds.w, image->mBounds.h);
- else
+ if (!image)
return false;
+
+ return drawImage(image, 0, 0, x, y, image->mBounds.w, image->mBounds.h);
}
bool Graphics::drawRescaledImage(Image *image, int srcX, int srcY,
@@ -160,15 +156,7 @@ bool Graphics::drawRescaledImage(Image *image, int srcX, int srcY,
bool useColor)
{
// Check that preconditions for blitting are met.
- if (!mTarget || !image)
- return false;
- if (!image->mSDLSurface)
- return false;
-
- Image *tmpImage = image->SDLgetScaledImage(desiredWidth, desiredHeight);
- bool returnValue = false;
-
- if (!tmpImage)
+ if (!mTarget || !image || !image->mTexture)
return false;
dstX += mClipStack.top().xOffset;
@@ -183,76 +171,35 @@ bool Graphics::drawRescaledImage(Image *image, int srcX, int srcY,
srcRect.x = srcX; srcRect.y = srcY;
srcRect.w = width;
srcRect.h = height;
+ dstRect.w = desiredWidth;
+ dstRect.h = desiredHeight;
- returnValue = !(SDL_BlitSurface(tmpImage->mSDLSurface, &srcRect,
- mTarget, &dstRect) < 0);
-
- tmpImage->decRef(Resource::DeleteImmediately);
-
- return returnValue;
+ return !(SDL_RenderCopy(mRenderer, image->mTexture, &srcRect, &dstRect) < 0);
}
bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY,
- int width, int height, bool)
+ int width, int height, bool useColor)
{
- // Check that preconditions for blitting are met.
- if (!mTarget || !image || !image->mSDLSurface)
+ if (!image)
return false;
- dstX += mClipStack.top().xOffset;
- dstY += mClipStack.top().yOffset;
-
- srcX += image->mBounds.x;
- srcY += image->mBounds.y;
-
- SDL_Rect dstRect;
- SDL_Rect srcRect;
- dstRect.x = dstX; dstRect.y = dstY;
- srcRect.x = srcX; srcRect.y = srcY;
- srcRect.w = width;
- srcRect.h = height;
-
- if (mBlitMode == BLIT_NORMAL)
- return !(SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect) < 0);
- else
- return !(SDL_gfxBlitRGBA(image->mSDLSurface, &srcRect, mTarget, &dstRect) < 0);
+ return drawRescaledImage(image,
+ srcX, srcY,
+ dstX, dstY,
+ width, height,
+ width, height, useColor);
}
void Graphics::drawImagePattern(Image *image, int x, int y, int w, int h)
{
// Check that preconditions for blitting are met.
- if (!mTarget || !image)
- return;
- if (!image->mSDLSurface)
+ if (!image)
return;
const int iw = image->getWidth();
const int ih = image->getHeight();
- if (iw == 0 || ih == 0)
- return;
-
- for (int py = 0; py < h; py += ih) // Y position on pattern plane
- {
- int dh = (py + ih >= h) ? h - py : ih;
- int srcY = image->mBounds.y;
- int dstY = y + py + mClipStack.top().yOffset;
-
- for (int px = 0; px < w; px += iw) // X position on pattern plane
- {
- int dw = (px + iw >= w) ? w - px : iw;
- int srcX = image->mBounds.x;
- int dstX = x + px + mClipStack.top().xOffset;
-
- SDL_Rect dstRect;
- SDL_Rect srcRect;
- dstRect.x = dstX; dstRect.y = dstY;
- srcRect.x = srcX; srcRect.y = srcY;
- srcRect.w = dw; srcRect.h = dh;
-
- SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect);
- }
- }
+ drawRescaledImagePattern(image, x, y, w, h, iw, ih);
}
void Graphics::drawRescaledImagePattern(Image *image,
@@ -261,50 +208,34 @@ void Graphics::drawRescaledImagePattern(Image *image,
int scaledWidth, int scaledHeight)
{
// Check that preconditions for blitting are met.
- if (!mTarget || !image)
- return;
- if (!image->mSDLSurface)
+ if (!mTarget || !image || !image->mTexture)
return;
if (scaledHeight == 0 || scaledWidth == 0)
return;
- Image *tmpImage = image->SDLgetScaledImage(scaledWidth, scaledHeight);
- if (!tmpImage)
- return;
-
- const int iw = tmpImage->getWidth();
- const int ih = tmpImage->getHeight();
-
- if (iw == 0 || ih == 0)
- {
- tmpImage->decRef(Resource::DeleteImmediately);
- return;
- }
-
- for (int py = 0; py < h; py += ih) // Y position on pattern plane
+ for (int py = 0; py < h; py += scaledHeight) // Y position on pattern plane
{
- int dh = (py + ih >= h) ? h - py : ih;
- int srcY = tmpImage->mBounds.y;
+ int dh = (py + scaledHeight >= h) ? h - py : scaledHeight;
+ int srcY = image->mBounds.y;
int dstY = y + py + mClipStack.top().yOffset;
- for (int px = 0; px < w; px += iw) // X position on pattern plane
+ for (int px = 0; px < w; px += scaledWidth) // X position on pattern plane
{
- int dw = (px + iw >= w) ? w - px : iw;
- int srcX = tmpImage->mBounds.x;
+ int dw = (px + scaledWidth >= w) ? w - px : scaledWidth;
+ int srcX = image->mBounds.x;
int dstX = x + px + mClipStack.top().xOffset;
SDL_Rect dstRect;
SDL_Rect srcRect;
dstRect.x = dstX; dstRect.y = dstY;
+ dstRect.w = dw; dstRect.h = dh;
srcRect.x = srcX; srcRect.y = srcY;
srcRect.w = dw; srcRect.h = dh;
- SDL_BlitSurface(tmpImage->mSDLSurface, &srcRect, mTarget, &dstRect);
+ SDL_RenderCopy(mRenderer, image->mTexture, &srcRect, &dstRect);
}
}
-
- tmpImage->decRef(Resource::DeleteImmediately);
}
void Graphics::drawImageRect(int x, int y, int w, int h,
@@ -361,7 +292,7 @@ void Graphics::drawImageRect(int x, int y, int w, int h,
void Graphics::updateScreen()
{
- SDL_Flip(mTarget);
+ SDL_RenderPresent(mRenderer);
}
SDL_Surface *Graphics::getScreenshot()
@@ -377,10 +308,140 @@ SDL_Surface *Graphics::getScreenshot()
#endif
int amask = 0x00000000;
- SDL_Surface *screenshot = SDL_CreateRGBSurface(SDL_SWSURFACE, mTarget->w,
- mTarget->h, 24, rmask, gmask, bmask, amask);
-
- SDL_BlitSurface(mTarget, NULL, screenshot, NULL);
+ SDL_Surface *screenshot = SDL_CreateRGBSurface(0, mWidth,
+ mHeight, 24, rmask, gmask, bmask, amask);
+ SDL_RenderReadPixels(mRenderer, NULL, SDL_PIXELFORMAT_RGB888, screenshot->pixels, screenshot->pitch);
return screenshot;
}
+
+bool Graphics::pushClipArea(gcn::Rectangle area)
+{
+ bool result = gcn::Graphics::pushClipArea(area);
+ updateSDLClipRect();
+ return result;
+}
+
+void Graphics::popClipArea()
+{
+ gcn::Graphics::popClipArea();
+ updateSDLClipRect();
+}
+
+void Graphics::updateSDLClipRect()
+{
+ if (mClipStack.empty())
+ {
+ SDL_RenderSetClipRect(mRenderer, NULL);
+ return;
+ }
+
+ const gcn::ClipRectangle &carea = mClipStack.top();
+ SDL_Rect rect;
+ rect.x = carea.x;
+ rect.y = carea.y;
+ rect.w = carea.width;
+ rect.h = carea.height;
+
+ SDL_RenderSetClipRect(mRenderer, &rect);
+}
+
+void Graphics::drawPoint(int x, int y)
+{
+ if (mClipStack.empty())
+ {
+ throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
+ }
+
+ const gcn::ClipRectangle &top = mClipStack.top();
+
+ x += top.xOffset;
+ y += top.yOffset;
+
+ if (!top.isPointInRect(x, y))
+ return;
+
+ SDL_SetRenderDrawColor(mRenderer,
+ (Uint8)(mColor.r),
+ (Uint8)(mColor.g),
+ (Uint8)(mColor.b),
+ (Uint8)(mColor.a));
+ SDL_RenderDrawPoint(mRenderer, x, y);
+}
+
+void Graphics::drawLine(int x1, int y1, int x2, int y2)
+{
+ if (mClipStack.empty())
+ {
+ throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
+ }
+
+ const gcn::ClipRectangle &top = mClipStack.top();
+
+ x1 += top.xOffset;
+ y1 += top.yOffset;
+ x2 += top.xOffset;
+ y2 += top.yOffset;
+
+ SDL_SetRenderDrawColor(mRenderer,
+ (Uint8)(mColor.r),
+ (Uint8)(mColor.g),
+ (Uint8)(mColor.b),
+ (Uint8)(mColor.a));
+ SDL_RenderDrawLine(mRenderer, x1, y1, x2, y2);
+}
+
+void Graphics::drawRectangle(const gcn::Rectangle &rectangle)
+{
+ if (mClipStack.empty())
+ {
+ throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
+ }
+
+ const gcn::ClipRectangle &top = mClipStack.top();
+
+ SDL_Rect rect;
+ rect.x = rectangle.x + top.xOffset;
+ rect.y = rectangle.y + top.yOffset;
+ rect.w = rectangle.width;
+ rect.h = rectangle.height;
+
+ SDL_SetRenderDrawColor(mRenderer,
+ (Uint8)(mColor.r),
+ (Uint8)(mColor.g),
+ (Uint8)(mColor.b),
+ (Uint8)(mColor.a));
+ SDL_RenderDrawRect(mRenderer, &rect);
+}
+
+void Graphics::fillRectangle(const gcn::Rectangle &rectangle)
+{
+ if (mClipStack.empty())
+ {
+ throw GCN_EXCEPTION("Clip stack is empty, perhaps you called a draw funtion outside of _beginDraw() and _endDraw()?");
+ }
+
+ const gcn::ClipRectangle &top = mClipStack.top();
+
+ gcn::Rectangle area = rectangle;
+ area.x += top.xOffset;
+ area.y += top.yOffset;
+
+ if(!area.isIntersecting(top))
+ {
+ return;
+ }
+
+ SDL_Rect rect;
+ rect.x = area.x;
+ rect.y = area.y;
+ rect.w = area.width;
+ rect.h = area.height;
+
+ SDL_SetRenderDrawColor(mRenderer,
+ (Uint8)(mColor.r),
+ (Uint8)(mColor.g),
+ (Uint8)(mColor.b),
+ (Uint8)(mColor.a));
+ SDL_RenderFillRect(mRenderer, &rect);
+}