From c9f8bba932022ffd90031713c51861587f86b244 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sat, 28 Dec 2013 23:06:17 +0300 Subject: Add cached draw methods into renderers. --- src/render/graphics.h | 9 ++ src/render/mobileopenglgraphics.cpp | 222 +++++++++++++++++++++++++++ src/render/mobileopenglgraphics.h | 16 ++ src/render/normalopenglgraphics.cpp | 294 ++++++++++++++++++++++++++++++++++++ src/render/normalopenglgraphics.h | 19 +++ src/render/nullopenglgraphics.cpp | 15 ++ src/render/nullopenglgraphics.h | 9 ++ src/render/safeopenglgraphics.cpp | 61 ++++++++ src/render/safeopenglgraphics.h | 9 ++ src/render/sdl2graphics.cpp | 83 ++++++++++ src/render/sdl2graphics.h | 9 ++ src/render/sdl2softwaregraphics.cpp | 202 ++++++++++++++++++++++++- src/render/sdl2softwaregraphics.h | 9 ++ src/render/sdlgraphics.cpp | 202 ++++++++++++++++++++++++- src/render/sdlgraphics.h | 9 ++ src/render/surfacegraphics.cpp | 38 +++++ src/render/surfacegraphics.h | 10 ++ 17 files changed, 1214 insertions(+), 2 deletions(-) diff --git a/src/render/graphics.h b/src/render/graphics.h index 2aa850d41..82bf220ab 100644 --- a/src/render/graphics.h +++ b/src/render/graphics.h @@ -385,6 +385,15 @@ class Graphics : public gcn::Graphics const int width, const int height, const bool useColor) = 0; + virtual void drawImageCached(const Image *const image, + int srcX, int srcY) = 0; + + virtual void drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) = 0; + + virtual void completeCache() = 0; + int mWidth; int mHeight; diff --git a/src/render/mobileopenglgraphics.cpp b/src/render/mobileopenglgraphics.cpp index a56510871..df11dae0a 100644 --- a/src/render/mobileopenglgraphics.cpp +++ b/src/render/mobileopenglgraphics.cpp @@ -49,9 +49,14 @@ MobileOpenGLGraphics::MobileOpenGLGraphics(): mIntTexArray(nullptr), mIntVertArray(nullptr), mShortVertArray(nullptr), + mFloatTexArrayCached(nullptr), + mShortVertArrayCached(nullptr), + mAlphaCached(1.0F), + mVpCached(0), mTexture(false), mIsByteColor(false), mByteColor(), + mImageCached(0), mFloatColor(1.0F), mMaxVertices(500), mColorAlpha(false), @@ -71,6 +76,8 @@ MobileOpenGLGraphics::~MobileOpenGLGraphics() delete [] mIntTexArray; delete [] mIntVertArray; delete [] mShortVertArray; + delete [] mFloatTexArrayCached; + delete [] mShortVertArrayCached; } void MobileOpenGLGraphics::initArrays() @@ -88,6 +95,8 @@ void MobileOpenGLGraphics::initArrays() mIntTexArray = new GLint[sz]; mIntVertArray = new GLint[sz]; mShortVertArray = new GLshort[sz]; + mFloatTexArrayCached = new GLfloat[sz]; + mShortVertArrayCached = new GLshort[sz]; } bool MobileOpenGLGraphics::setVideoMode(const int w, const int h, @@ -216,6 +225,208 @@ bool MobileOpenGLGraphics::drawImage2(const Image *const image, return true; } +void MobileOpenGLGraphics::drawImageCached(const Image *const image, + int x, int y) +{ + if (!image) + return; + + if (image->mGLImage != mImageCached) + { + completeCache(); + mImageCached = image->mGLImage; + mAlphaCached = image->mAlpha; + } + + const SDL_Rect &imageRect = image->mBounds; + const int srcX = imageRect.x; + const int srcY = imageRect.y; + const int w = imageRect.w; + const int h = imageRect.h; + + if (w == 0 || h == 0) + return; + + const float tw = static_cast(image->mTexWidth); + const float th = static_cast(image->mTexHeight); + + const unsigned int vLimit = mMaxVertices * 4; + + unsigned int vp = mVpCached; + + // Draw a set of textured rectangles +// if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + float texX1 = static_cast(srcX) / tw; + float texY1 = static_cast(srcY) / th; + float texX2 = static_cast(srcX + w) / tw; + float texY2 = static_cast(srcY + h) / th; + + mFloatTexArrayCached[vp + 0] = texX1; + mFloatTexArrayCached[vp + 1] = texY1; + + mFloatTexArrayCached[vp + 2] = texX2; + mFloatTexArrayCached[vp + 3] = texY1; + + mFloatTexArrayCached[vp + 4] = texX2; + mFloatTexArrayCached[vp + 5] = texY2; + + mFloatTexArrayCached[vp + 6] = texX1; + mFloatTexArrayCached[vp + 7] = texY1; + + mFloatTexArrayCached[vp + 8] = texX1; + mFloatTexArrayCached[vp + 9] = texY2; + + mFloatTexArrayCached[vp + 10] = texX2; + mFloatTexArrayCached[vp + 11] = texY2; + + mShortVertArray[vp + 0] = x; + mShortVertArray[vp + 1] = y; + + mShortVertArray[vp + 2] = x + w; + mShortVertArray[vp + 3] = y; + + mShortVertArray[vp + 4] = x + w; + mShortVertArray[vp + 5] = y + h; + + mShortVertArray[vp + 6] = x; + mShortVertArray[vp + 7] = y; + + mShortVertArray[vp + 8] = x; + mShortVertArray[vp + 9] = y + h; + + mShortVertArray[vp + 10] = x + w; + mShortVertArray[vp + 11] = y + h; + + vp += 12; + if (vp >= vLimit) + { + completeCache(); + vp = 0; + } + else + { + mVpCached = vp; + } + } +} + +void MobileOpenGLGraphics::drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) +{ + if (!image) + return; + + if (image->mGLImage != mImageCached) + { + completeCache(); + mImageCached = image->mGLImage; + } + + const SDL_Rect &imageRect = image->mBounds; + const int srcX = imageRect.x; + const int srcY = imageRect.y; + const int iw = imageRect.w; + const int ih = imageRect.h; + + if (iw == 0 || ih == 0) + return; + + const float tw = static_cast(image->mTexWidth); + const float th = static_cast(image->mTexHeight); + + unsigned int vp = mVpCached; + const unsigned int vLimit = mMaxVertices * 4; + // Draw a set of textured rectangles +// if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) +// { + const float texX1 = static_cast(srcX) / tw; + const float texY1 = static_cast(srcY) / th; + + for (int py = 0; py < h; py += ih) + { + const int height = (py + ih >= h) ? h - py : ih; + const float texY2 = static_cast(srcY + height) / th; + const int dstY = y + py; + for (int px = 0; px < w; px += iw) + { + const int width = (px + iw >= w) ? w - px : iw; + const int dstX = x + px; + + const float texX2 = static_cast(srcX + width) / tw; + + mFloatTexArrayCached[vp + 0] = texX1; // 1 + mFloatTexArrayCached[vp + 1] = texY1; + + mFloatTexArrayCached[vp + 2] = texX2; // 2 + mFloatTexArrayCached[vp + 3] = texY1; + + mFloatTexArrayCached[vp + 4] = texX2; // 3 + mFloatTexArrayCached[vp + 5] = texY2; + + mFloatTexArrayCached[vp + 6] = texX1; // 1 + mFloatTexArrayCached[vp + 7] = texY1; + + mFloatTexArrayCached[vp + 8] = texX1; // 4 + mFloatTexArrayCached[vp + 9] = texY2; + + mFloatTexArrayCached[vp + 10] = texX2; // 3 + mFloatTexArrayCached[vp + 11] = texY2; + + mShortVertArrayCached[vp + 0] = static_cast(dstX); + mShortVertArrayCached[vp + 1] = static_cast(dstY); + + mShortVertArrayCached[vp + 2] = static_cast( + dstX + width); + mShortVertArrayCached[vp + 3] = static_cast(dstY); + + mShortVertArrayCached[vp + 4] = static_cast( + dstX + width); + mShortVertArrayCached[vp + 5] = static_cast( + dstY + height); + + mShortVertArrayCached[vp + 6] = static_cast(dstX); + mShortVertArrayCached[vp + 7] = static_cast(dstY); + + mShortVertArrayCached[vp + 8] = static_cast(dstX); + mShortVertArrayCached[vp + 9] = static_cast( + dstY + height); + + mShortVertArrayCached[vp + 10] = static_cast( + dstX + width); + mShortVertArrayCached[vp + 11] = static_cast( + dstY + height); + + vp += 12; + if (vp >= vLimit) + { + completeCache(); + vp = 0; + } + } + } +// } + mVpCached = vp; +} + +void MobileOpenGLGraphics::completeCache() +{ + if (!mImageCached) + return; + + setColorAlpha(mAlphaCached); +#ifdef DEBUG_BIND_TEXTURE +// debugBindTexture(image); +#endif + bindTexture(OpenGLImageHelper::mTextureType, mImageCached); + setTexturingAndBlending(true); + + drawTriangleArrayfsCached(mVpCached); + mImageCached = 0; + mVpCached = 0; +} + bool MobileOpenGLGraphics::drawRescaledImage(const Image *const image, int srcX, int srcY, int dstX, int dstY, @@ -1202,6 +1413,17 @@ inline void MobileOpenGLGraphics::drawTriangleArrayfs(const int size) glDrawArrays(GL_TRIANGLES, 0, size / 2); } +inline void MobileOpenGLGraphics::drawTriangleArrayfsCached(const int size) +{ + glVertexPointer(2, GL_SHORT, 0, mShortVertArrayCached); + glTexCoordPointer(2, GL_FLOAT, 0, mFloatTexArrayCached); + +#ifdef DEBUG_DRAW_CALLS + mDrawCalls ++; +#endif + glDrawArrays(GL_TRIANGLES, 0, size / 2); +} + inline void MobileOpenGLGraphics::drawTriangleArrayfs(const GLshort *const shortVertArray, const GLfloat *const diff --git a/src/render/mobileopenglgraphics.h b/src/render/mobileopenglgraphics.h index 8a2469267..dbee649d0 100644 --- a/src/render/mobileopenglgraphics.h +++ b/src/render/mobileopenglgraphics.h @@ -165,6 +165,8 @@ class MobileOpenGLGraphics final : public Graphics inline void drawTriangleArrayfs(const int size); + inline void drawTriangleArrayfsCached(const int size); + inline void drawLineArrays(const int size); inline void drawVertexes(const NormalOpenGLGraphicsVertexes &ogl); @@ -193,6 +195,15 @@ class MobileOpenGLGraphics final : public Graphics const int width, const int height, const bool useColor) override final; + void drawImageCached(const Image *const image, + int x, int y) override final; + + void drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) override final; + + void completeCache() override final; + #ifdef DEBUG_DRAW_CALLS unsigned int getDrawCalls() const { return mLastDrawCalls; } @@ -220,10 +231,15 @@ class MobileOpenGLGraphics final : public Graphics GLint *mIntTexArray; GLint *mIntVertArray; GLshort *mShortVertArray; + GLfloat *mFloatTexArrayCached; + GLshort *mShortVertArrayCached; + float mAlphaCached; + int mVpCached; bool mTexture; bool mIsByteColor; gcn::Color mByteColor; + GLuint mImageCached; float mFloatColor; int mMaxVertices; bool mColorAlpha; diff --git a/src/render/normalopenglgraphics.cpp b/src/render/normalopenglgraphics.cpp index 88a9f448f..018ade537 100644 --- a/src/render/normalopenglgraphics.cpp +++ b/src/render/normalopenglgraphics.cpp @@ -51,9 +51,15 @@ NormalOpenGLGraphics::NormalOpenGLGraphics(): mFloatTexArray(nullptr), mIntTexArray(nullptr), mIntVertArray(nullptr), + mFloatTexArrayCached(nullptr), + mIntTexArrayCached(nullptr), + mIntVertArrayCached(nullptr), + mAlphaCached(1.0F), + mVpCached(0), mTexture(false), mIsByteColor(false), mByteColor(), + mImageCached(0), mFloatColor(1.0F), mMaxVertices(500), mColorAlpha(false), @@ -72,6 +78,9 @@ NormalOpenGLGraphics::~NormalOpenGLGraphics() delete [] mFloatTexArray; delete [] mIntTexArray; delete [] mIntVertArray; + delete [] mFloatTexArrayCached; + delete [] mIntTexArrayCached; + delete [] mIntVertArrayCached; } void NormalOpenGLGraphics::initArrays() @@ -88,6 +97,9 @@ void NormalOpenGLGraphics::initArrays() mFloatTexArray = new GLfloat[sz]; mIntTexArray = new GLint[sz]; mIntVertArray = new GLint[sz]; + mFloatTexArrayCached = new GLfloat[sz]; + mIntTexArrayCached = new GLint[sz]; + mIntVertArrayCached = new GLint[sz]; } bool NormalOpenGLGraphics::setVideoMode(const int w, const int h, @@ -263,6 +275,266 @@ bool NormalOpenGLGraphics::drawImage2(const Image *const image, return true; } +void NormalOpenGLGraphics::drawImageCached(const Image *const image, + int x, int y) +{ + if (!image) + return; + + if (image->mGLImage != mImageCached) + { + completeCache(); + mImageCached = image->mGLImage; + mAlphaCached = image->mAlpha; + } + + const SDL_Rect &imageRect = image->mBounds; + const int w = imageRect.w; + const int h = imageRect.h; + + if (w == 0 || h == 0) + return; + + const int srcX = imageRect.x; + const int srcY = imageRect.y; + + const float tw = static_cast(image->mTexWidth); + const float th = static_cast(image->mTexHeight); + + const unsigned int vLimit = mMaxVertices * 4; + + unsigned int vp = mVpCached; + + // Draw a set of textured rectangles + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + const float texX1 = static_cast(srcX) / tw; + const float texY1 = static_cast(srcY) / th; + + const float texX2 = static_cast(srcX + w) / tw; + const float texY2 = static_cast(srcY + h) / th; + + mFloatTexArrayCached[vp + 0] = texX1; + mFloatTexArrayCached[vp + 1] = texY1; + + mFloatTexArrayCached[vp + 2] = texX2; + mFloatTexArrayCached[vp + 3] = texY1; + + mFloatTexArrayCached[vp + 4] = texX2; + mFloatTexArrayCached[vp + 5] = texY2; + + mFloatTexArrayCached[vp + 6] = texX1; + mFloatTexArrayCached[vp + 7] = texY2; + + mIntVertArrayCached[vp + 0] = x; + mIntVertArrayCached[vp + 1] = y; + + mIntVertArrayCached[vp + 2] = x + w; + mIntVertArrayCached[vp + 3] = y; + + mIntVertArrayCached[vp + 4] = x + w; + mIntVertArrayCached[vp + 5] = y + h; + + mIntVertArrayCached[vp + 6] = x; + mIntVertArrayCached[vp + 7] = y + h; + + vp += 8; + if (vp >= vLimit) + { + completeCache(); + vp = 0; + } + else + { + mVpCached = vp; + } + } + else + { + mIntTexArrayCached[vp + 0] = srcX; + mIntTexArrayCached[vp + 1] = srcY; + + mIntTexArrayCached[vp + 2] = srcX + w; + mIntTexArrayCached[vp + 3] = srcY; + + mIntTexArrayCached[vp + 4] = srcX + w; + mIntTexArrayCached[vp + 5] = srcY + h; + + mIntTexArrayCached[vp + 6] = srcX; + mIntTexArrayCached[vp + 7] = srcY + h; + + mIntVertArrayCached[vp + 0] = x; + mIntVertArrayCached[vp + 1] = y; + + mIntVertArrayCached[vp + 2] = x + w; + mIntVertArrayCached[vp + 3] = y; + + mIntVertArrayCached[vp + 4] = x + w; + mIntVertArrayCached[vp + 5] = y + h; + + mIntVertArrayCached[vp + 6] = x; + mIntVertArrayCached[vp + 7] = y + h; + + vp += 8; + if (vp >= vLimit) + { + completeCache(); + vp = 0; + } + else + { + mVpCached = vp; + } + } +} + +void NormalOpenGLGraphics::drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) +{ + FUNC_BLOCK("Graphics::drawPatternCached", 1) + if (!image) + return; + + if (image->mGLImage != mImageCached) + { + completeCache(); + mImageCached = image->mGLImage; + } + + const SDL_Rect &imageRect = image->mBounds; + const int srcX = imageRect.x; + const int srcY = imageRect.y; + const int iw = imageRect.w; + const int ih = imageRect.h; + + if (iw == 0 || ih == 0) + return; + + const float tw = static_cast(image->mTexWidth); + const float th = static_cast(image->mTexHeight); + + unsigned int vp = mVpCached; + const unsigned int vLimit = mMaxVertices * 4; + // Draw a set of textured rectangles + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + const float texX1 = static_cast(srcX) / tw; + const float texY1 = static_cast(srcY) / th; + + for (int py = 0; py < h; py += ih) + { + const int height = (py + ih >= h) ? h - py : ih; + const int dstY = y + py; + const float texY2 = static_cast(srcY + height) / th; + for (int px = 0; px < w; px += iw) + { + const int width = (px + iw >= w) ? w - px : iw; + const int dstX = x + px; + + const float texX2 = static_cast(srcX + width) / tw; + + mFloatTexArrayCached[vp + 0] = texX1; + mFloatTexArrayCached[vp + 1] = texY1; + + mFloatTexArrayCached[vp + 2] = texX2; + mFloatTexArrayCached[vp + 3] = texY1; + + mFloatTexArrayCached[vp + 4] = texX2; + mFloatTexArrayCached[vp + 5] = texY2; + + mFloatTexArrayCached[vp + 6] = texX1; + mFloatTexArrayCached[vp + 7] = texY2; + + mIntVertArrayCached[vp + 0] = dstX; + mIntVertArrayCached[vp + 1] = dstY; + + mIntVertArrayCached[vp + 2] = dstX + width; + mIntVertArrayCached[vp + 3] = dstY; + + mIntVertArrayCached[vp + 4] = dstX + width; + mIntVertArrayCached[vp + 5] = dstY + height; + + mIntVertArrayCached[vp + 6] = dstX; + mIntVertArrayCached[vp + 7] = dstY + height; + + vp += 8; + if (vp >= vLimit) + { + completeCache(); + vp = 0; + } + } + } + } + else + { + for (int py = 0; py < h; py += ih) + { + const int height = (py + ih >= h) ? h - py : ih; + const int dstY = y + py; + for (int px = 0; px < w; px += iw) + { + const int width = (px + iw >= w) ? w - px : iw; + const int dstX = x + px; + + mIntTexArrayCached[vp + 0] = srcX; + mIntTexArrayCached[vp + 1] = srcY; + + mIntTexArrayCached[vp + 2] = srcX + width; + mIntTexArrayCached[vp + 3] = srcY; + + mIntTexArrayCached[vp + 4] = srcX + width; + mIntTexArrayCached[vp + 5] = srcY + height; + + mIntTexArrayCached[vp + 6] = srcX; + mIntTexArrayCached[vp + 7] = srcY + height; + + mIntVertArrayCached[vp + 0] = dstX; + mIntVertArrayCached[vp + 1] = dstY; + + mIntVertArrayCached[vp + 2] = dstX + width; + mIntVertArrayCached[vp + 3] = dstY; + + mIntVertArrayCached[vp + 4] = dstX + width; + mIntVertArrayCached[vp + 5] = dstY + height; + + mIntVertArrayCached[vp + 6] = dstX; + mIntVertArrayCached[vp + 7] = dstY + height; + + vp += 8; + if (vp >= vLimit) + { + completeCache(); + vp = 0; + } + } + } + } + mVpCached = vp; +} + +void NormalOpenGLGraphics::completeCache() +{ + if (!mImageCached) + return; + + setColorAlpha(mAlphaCached); +#ifdef DEBUG_BIND_TEXTURE +// debugBindTexture(image); +#endif + bindTexture(OpenGLImageHelper::mTextureType, mImageCached); + setTexturingAndBlending(true); + + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + drawQuadArrayfiCached(mVpCached); + else + drawQuadArrayiiCached(mVpCached); + + mImageCached = 0; + mVpCached = 0; +} + bool NormalOpenGLGraphics::drawRescaledImage(const Image *const image, int srcX, int srcY, int dstX, int dstY, @@ -1391,6 +1663,17 @@ inline void NormalOpenGLGraphics::drawQuadArrayfi(const int size) glDrawArrays(GL_QUADS, 0, size / 2); } +inline void NormalOpenGLGraphics::drawQuadArrayfiCached(const int size) +{ + glVertexPointer(2, GL_INT, 0, mIntVertArrayCached); + glTexCoordPointer(2, GL_FLOAT, 0, mFloatTexArrayCached); + +#ifdef DEBUG_DRAW_CALLS + mDrawCalls ++; +#endif + glDrawArrays(GL_QUADS, 0, size / 2); +} + inline void NormalOpenGLGraphics::drawQuadArrayfi(const GLint *const intVertArray, const GLfloat *const @@ -1417,6 +1700,17 @@ inline void NormalOpenGLGraphics::drawQuadArrayii(const int size) glDrawArrays(GL_QUADS, 0, size / 2); } +inline void NormalOpenGLGraphics::drawQuadArrayiiCached(const int size) +{ + glVertexPointer(2, GL_INT, 0, mIntVertArrayCached); + glTexCoordPointer(2, GL_INT, 0, mIntTexArrayCached); + +#ifdef DEBUG_DRAW_CALLS + mDrawCalls ++; +#endif + glDrawArrays(GL_QUADS, 0, size / 2); +} + inline void NormalOpenGLGraphics::drawQuadArrayii(const GLint *const intVertArray, const GLint *const diff --git a/src/render/normalopenglgraphics.h b/src/render/normalopenglgraphics.h index a62a97df7..73457ef0d 100644 --- a/src/render/normalopenglgraphics.h +++ b/src/render/normalopenglgraphics.h @@ -160,12 +160,16 @@ class NormalOpenGLGraphics final : public Graphics inline void drawQuadArrayfi(const int size); + inline void drawQuadArrayfiCached(const int size); + inline void drawQuadArrayfi(const GLint *const intVertArray, const GLfloat *const floatTexArray, const int size); inline void drawQuadArrayii(const int size); + inline void drawQuadArrayiiCached(const int size); + inline void drawQuadArrayii(const GLint *const intVertArray, const GLint *const intTexArray, const int size); @@ -200,6 +204,15 @@ class NormalOpenGLGraphics final : public Graphics const int width, const int height, const bool useColor) override final; + void drawImageCached(const Image *const image, + int x, int y) override final; + + void drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) override final; + + void completeCache() override final; + #ifdef DEBUG_DRAW_CALLS unsigned int getDrawCalls() const { return mLastDrawCalls; } @@ -229,10 +242,16 @@ class NormalOpenGLGraphics final : public Graphics GLfloat *mFloatTexArray; GLint *mIntTexArray; GLint *mIntVertArray; + GLfloat *mFloatTexArrayCached; + GLint *mIntTexArrayCached; + GLint *mIntVertArrayCached; + float mAlphaCached; + int mVpCached; bool mTexture; bool mIsByteColor; gcn::Color mByteColor; + GLuint mImageCached; float mFloatColor; int mMaxVertices; bool mColorAlpha; diff --git a/src/render/nullopenglgraphics.cpp b/src/render/nullopenglgraphics.cpp index 0bee724ee..ab1291233 100644 --- a/src/render/nullopenglgraphics.cpp +++ b/src/render/nullopenglgraphics.cpp @@ -166,6 +166,21 @@ bool NullOpenGLGraphics::drawImage2(const Image *const image, return true; } +void NullOpenGLGraphics::drawImageCached(const Image *const image, + int x, int y) +{ +} + +void NullOpenGLGraphics::drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) +{ +} + +void NullOpenGLGraphics::completeCache() +{ +} + bool NullOpenGLGraphics::drawRescaledImage(const Image *const image, int srcX, int srcY, int dstX, int dstY, diff --git a/src/render/nullopenglgraphics.h b/src/render/nullopenglgraphics.h index bf424bb8d..7b15cfbf5 100644 --- a/src/render/nullopenglgraphics.h +++ b/src/render/nullopenglgraphics.h @@ -200,6 +200,15 @@ class NullOpenGLGraphics final : public Graphics const int width, const int height, const bool useColor) override final; + void drawImageCached(const Image *const image, + int x, int y) override final; + + void drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) override final; + + void completeCache() override final; + #ifdef DEBUG_DRAW_CALLS unsigned int getDrawCalls() const { return mLastDrawCalls; } diff --git a/src/render/safeopenglgraphics.cpp b/src/render/safeopenglgraphics.cpp index e1540dbab..1170f0300 100644 --- a/src/render/safeopenglgraphics.cpp +++ b/src/render/safeopenglgraphics.cpp @@ -165,6 +165,67 @@ bool SafeOpenGLGraphics::drawImage2(const Image *const image, return true; } +void SafeOpenGLGraphics::drawImageCached(const Image *const image, + int x, int y) +{ + FUNC_BLOCK("Graphics::drawImageCached", 1) + if (!image) + return; + + setColorAlpha(image->mAlpha); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + setTexturingAndBlending(true); + + const SDL_Rect &bounds = image->mBounds; + // Draw a textured quad. + glBegin(GL_QUADS); + drawQuad(image, bounds.x, bounds.y, x, y, bounds.w, bounds.h); + glEnd(); +} + +void SafeOpenGLGraphics::drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) +{ + FUNC_BLOCK("Graphics::drawPatternCached", 1) + if (!image) + return; + + const SDL_Rect &imageRect = image->mBounds; + const int iw = imageRect.w; + const int ih = imageRect.h; + if (iw == 0 || ih == 0) + return; + + const int srcX = imageRect.x; + const int srcY = imageRect.y; + + setColorAlpha(image->mAlpha); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + setTexturingAndBlending(true); + + // Draw a set of textured rectangles + glBegin(GL_QUADS); + + for (int py = 0; py < h; py += ih) + { + const int height = (py + ih >= h) ? h - py : ih; + const int dstY = y + py; + for (int px = 0; px < w; px += iw) + { + int width = (px + iw >= w) ? w - px : iw; + int dstX = x + px; + drawQuad(image, srcX, srcY, dstX, dstY, width, height); + } + } + + glEnd(); +} + +void SafeOpenGLGraphics::completeCache() +{ +} + bool SafeOpenGLGraphics::drawRescaledImage(const Image *const image, int srcX, int srcY, int dstX, int dstY, const int width, const int height, diff --git a/src/render/safeopenglgraphics.h b/src/render/safeopenglgraphics.h index 60a726845..dac61cb47 100644 --- a/src/render/safeopenglgraphics.h +++ b/src/render/safeopenglgraphics.h @@ -163,6 +163,15 @@ class SafeOpenGLGraphics final : public Graphics const int width, const int height, const bool useColor) override final; + void drawImageCached(const Image *const image, + int x, int y) override final; + + void drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) override final; + + void completeCache() override final; + static void bindTexture(const GLenum target, const GLuint texture); static GLuint mLastImage; diff --git a/src/render/sdl2graphics.cpp b/src/render/sdl2graphics.cpp index 6426506ee..00452d9c6 100644 --- a/src/render/sdl2graphics.cpp +++ b/src/render/sdl2graphics.cpp @@ -149,6 +149,89 @@ bool SDLGraphics::drawImage2(const Image *const image, int srcX, int srcY, return !MSDL_RenderCopy(mRenderer, image->mTexture, &srcRect, &dstRect); } +void SDLGraphics::drawImageCached(const Image *const image, + int x, int y) +{ + FUNC_BLOCK("Graphics::drawImageCached", 1) + // Check that preconditions for blitting are met. + if (!mWindow || !image || !image->mTexture) + return; + + const gcn::ClipRectangle &top = mClipStack.top(); + if (!top.width || !top.height) + return; + + const SDL_Rect &bounds = image->mBounds; + const SDL_Rect srcRect = + { + static_cast(bounds.x), + static_cast(bounds.y), + static_cast(bounds.w), + static_cast(bounds.h) + }; + + const SDL_Rect dstRect = + { + static_cast(x + top.xOffset), + static_cast(y + top.yOffset), + static_cast(bounds.w), + static_cast(bounds.h) + }; + + MSDL_RenderCopy(mRenderer, image->mTexture, &srcRect, &dstRect); +} + +void SDLGraphics::drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) +{ + FUNC_BLOCK("Graphics::drawPatternCached", 1) + // Check that preconditions for blitting are met. + if (!mWindow || !image) + return; + if (!image->mTexture) + return; + + const gcn::ClipRectangle &top = mClipStack.top(); + if (!top.width || !top.height) + return; + + const SDL_Rect &bounds = image->mBounds; + const int iw = bounds.w; + const int ih = bounds.h; + if (iw == 0 || ih == 0) + return; + + const int xOffset = top.xOffset + x; + const int yOffset = top.yOffset + y; + + SDL_Rect dstRect; + SDL_Rect srcRect; + srcRect.x = static_cast(bounds.x); + srcRect.y = static_cast(bounds.y); + for (int py = 0; py < h; py += ih) + { + const int dh = (py + ih >= h) ? h - py : ih; + dstRect.y = static_cast(py + yOffset); + srcRect.h = static_cast(dh); + dstRect.h = static_cast(dh); + + for (int px = 0; px < w; px += iw) + { + const int dw = (px + iw >= w) ? w - px : iw; + dstRect.x = static_cast(px + xOffset); + srcRect.w = static_cast(dw); + dstRect.w = static_cast(dw); + + MSDL_RenderCopy(mRenderer, image->mTexture, &srcRect, &dstRect); + } + } +} + +void SDLGraphics::completeCache() +{ +} + void SDLGraphics::drawPattern(const Image *const image, const int x, const int y, const int w, const int h) diff --git a/src/render/sdl2graphics.h b/src/render/sdl2graphics.h index cbb2ff901..f1960d358 100644 --- a/src/render/sdl2graphics.h +++ b/src/render/sdl2graphics.h @@ -142,6 +142,15 @@ class SDLGraphics final : public Graphics const int width, const int height, const bool useColor) override final; + void drawImageCached(const Image *const image, + int x, int y) override final; + + void drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) override final; + + void completeCache() override final; + protected: uint32_t mRendererFlags; uint32_t mOldPixel; diff --git a/src/render/sdl2softwaregraphics.cpp b/src/render/sdl2softwaregraphics.cpp index e4e3d822f..b0d76bd57 100644 --- a/src/render/sdl2softwaregraphics.cpp +++ b/src/render/sdl2softwaregraphics.cpp @@ -125,7 +125,6 @@ bool SDL2SoftwareGraphics::drawImage2(const Image *const image, const gcn::ClipRectangle &top = mClipStack.top(); const SDL_Rect &bounds = image->mBounds; - SDL_Surface *const src = image->mSDLSurface; srcX += bounds.x; @@ -203,6 +202,207 @@ bool SDL2SoftwareGraphics::drawImage2(const Image *const image, return 0; } +void SDL2SoftwareGraphics::drawImageCached(const Image *const image, + int x, int y) +{ + FUNC_BLOCK("Graphics::drawImageCached", 1) + // Check that preconditions for blitting are met. + if (!mSurface || !image || !image->mSDLSurface) + return; + + const gcn::ClipRectangle &top = mClipStack.top(); + const SDL_Rect &bounds = image->mBounds; + + SDL_Surface *const src = image->mSDLSurface; + + int srcX = bounds.x; + const int srcY = bounds.y; + x += top.xOffset; + y += top.yOffset; + + int w = bounds.w; + int h = bounds.h; + if (srcX < 0) + { + w += srcX; + x -= static_cast(srcX); + srcX = 0; + } + const int maxw = src->w - srcX; + if (maxw < w) + w = maxw; + + if (srcY < 0) + { + h += srcY; + y -= static_cast(srcY); + srcY = 0; + } + const int maxh = src->h - srcY; + if (maxh < h) + h = maxh; + + const SDL_Rect *const clip = &mSurface->clip_rect; + const int clipX = clip->x; + const int clipY = clip->y; + int dx = clipX - x; + if (dx > 0) + { + w -= dx; + x += static_cast(dx); + srcX += dx; + } + dx = x + w - clipX - clip->w; + if (dx > 0) + w -= dx; + + int dy = clipY - y; + if (dy > 0) + { + h -= dy; + y += static_cast(dy); + srcY += dy; + } + dy = y + h - clipY - clip->h; + if (dy > 0) + h -= dy; + + if (w > 0 && h > 0) + { + SDL_Rect srcRect = + { + static_cast(srcX), + static_cast(srcY), + static_cast(w), + static_cast(h) + }; + + SDL_Rect dstRect = + { + static_cast(x), + static_cast(y), + static_cast(w), + static_cast(h) + }; + + SDL_LowerBlit(src, &srcRect, mSurface, &dstRect); + } +} + +void SDL2SoftwareGraphics::drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) +{ + FUNC_BLOCK("Graphics::drawPatternCached", 1) + // Check that preconditions for blitting are met. + if (!mSurface || !image) + return; + if (!image->mSDLSurface) + return; + + const SDL_Rect &bounds = image->mBounds; + const int iw = bounds.w; + const int ih = bounds.h; + if (iw == 0 || ih == 0) + return; + + const gcn::ClipRectangle &top = mClipStack.top(); + const int xOffset = top.xOffset + x; + const int yOffset = top.yOffset + y; + const int srcX = bounds.x; + const int srcY = bounds.y; + SDL_Surface *const src = image->mSDLSurface; + const SDL_Rect *const clip = &mSurface->clip_rect; + const int clipX = clip->x; + const int clipY = clip->y; + + for (int py = 0; py < h; py += ih) + { + const int dh = (py + ih >= h) ? h - py : ih; + int dstY = py + yOffset; + int y2 = srcY; + int h2 = dh; + if (y2 < 0) + { + h2 += y2; + dstY -= static_cast(y2); + y2 = 0; + } + const int maxh = src->h - y2; + if (maxh < h2) + h2 = maxh; + + int dy = clipY - dstY; + if (dy > 0) + { + h2 -= dy; + dstY += static_cast(dy); + y2 += dy; + } + dy = dstY + h2 - clipY - clip->h; + if (dy > 0) + h2 -= dy; + + if (h2 > 0) + { + for (int px = 0; px < w; px += iw) + { + const int dw = (px + iw >= w) ? w - px : iw; + int dstX = px + xOffset; + int x2 = srcX; + int w2 = dw; + if (x2 < 0) + { + w2 += x2; + dstX -= static_cast(x2); + x2 = 0; + } + const int maxw = src->w - x2; + if (maxw < w2) + w2 = maxw; + + int dx = clipX - dstX; + if (dx > 0) + { + w2 -= dx; + dstX += static_cast(dx); + x2 += dx; + } + dx = dstX + w2 - clipX - clip->w; + if (dx > 0) + w2 -= dx; + + if (w2 > 0) + { + SDL_Rect srcRect = + { + static_cast(x2), + static_cast(y2), + static_cast(w2), + static_cast(h2) + }; + + SDL_Rect dstRect = + { + static_cast(dstX), + static_cast(dstY), + static_cast(w2), + static_cast(h2) + }; + + SDL_LowerBlit(src, &srcRect, mSurface, &dstRect); + } + +// SDL_BlitSurface(image->mSDLSurface, &srcRect, mWindow, &dstRect); + } + } + } +} + +void SDL2SoftwareGraphics::completeCache() +{ +} + void SDL2SoftwareGraphics::drawPattern(const Image *const image, const int x, const int y, const int w, const int h) diff --git a/src/render/sdl2softwaregraphics.h b/src/render/sdl2softwaregraphics.h index 609ef6cf5..ab9fb7ce4 100644 --- a/src/render/sdl2softwaregraphics.h +++ b/src/render/sdl2softwaregraphics.h @@ -145,6 +145,15 @@ class SDL2SoftwareGraphics final : public Graphics const int width, const int height, const bool useColor) override final; + void drawImageCached(const Image *const image, + int x, int y) override final; + + void drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) override final; + + void completeCache() override final; + protected: int SDL_FakeUpperBlit(const SDL_Surface *const src, SDL_Rect *const srcrect, diff --git a/src/render/sdlgraphics.cpp b/src/render/sdlgraphics.cpp index f62d9dd56..c46b65000 100644 --- a/src/render/sdlgraphics.cpp +++ b/src/render/sdlgraphics.cpp @@ -116,7 +116,6 @@ bool SDLGraphics::drawImage2(const Image *const image, int srcX, int srcY, const gcn::ClipRectangle &top = mClipStack.top(); const SDL_Rect &bounds = image->mBounds; - SDL_Surface *const src = image->mSDLSurface; srcX += bounds.x; @@ -194,6 +193,207 @@ bool SDLGraphics::drawImage2(const Image *const image, int srcX, int srcY, return 0; } +void SDLGraphics::drawImageCached(const Image *const image, + int x, int y) +{ + FUNC_BLOCK("Graphics::drawImageCached", 1) + // Check that preconditions for blitting are met. + if (!mWindow || !image || !image->mSDLSurface) + return; + + const gcn::ClipRectangle &top = mClipStack.top(); + const SDL_Rect &bounds = image->mBounds; + + SDL_Surface *const src = image->mSDLSurface; + + int srcX = bounds.x; + int srcY = bounds.y; + x += top.xOffset; + y += top.yOffset; + + int w = bounds.w; + int h = bounds.h; + if (srcX < 0) + { + w += srcX; + x -= static_cast(srcX); + srcX = 0; + } + const int maxw = src->w - srcX; + if (maxw < w) + w = maxw; + + if (srcY < 0) + { + h += srcY; + y -= static_cast(srcY); + srcY = 0; + } + const int maxh = src->h - srcY; + if (maxh < h) + h = maxh; + + const SDL_Rect *const clip = &mWindow->clip_rect; + const int clipX = clip->x; + const int clipY = clip->y; + int dx = clipX - x; + if (dx > 0) + { + w -= dx; + x += static_cast(dx); + srcX += dx; + } + dx = x + w - clipX - clip->w; + if (dx > 0) + w -= dx; + + int dy = clipY - y; + if (dy > 0) + { + h -= dy; + y += static_cast(dy); + srcY += dy; + } + dy = y + h - clipY - clip->h; + if (dy > 0) + h -= dy; + + if (w > 0 && h > 0) + { + SDL_Rect srcRect = + { + static_cast(srcX), + static_cast(srcY), + static_cast(w), + static_cast(h) + }; + + SDL_Rect dstRect = + { + static_cast(x), + static_cast(y), + static_cast(w), + static_cast(h) + }; + + SDL_LowerBlit(src, &srcRect, mWindow, &dstRect); + } +} + +void SDLGraphics::drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) +{ + FUNC_BLOCK("Graphics::drawPatternCached", 1) + // Check that preconditions for blitting are met. + if (!mWindow || !image) + return; + if (!image->mSDLSurface) + return; + + const SDL_Rect &bounds = image->mBounds; + const int iw = bounds.w; + const int ih = bounds.h; + if (iw == 0 || ih == 0) + return; + + const gcn::ClipRectangle &top = mClipStack.top(); + const int xOffset = top.xOffset + x; + const int yOffset = top.yOffset + y; + const int srcX = bounds.x; + const int srcY = bounds.y; + SDL_Surface *const src = image->mSDLSurface; + const SDL_Rect *const clip = &mWindow->clip_rect; + const int clipX = clip->x; + const int clipY = clip->y; + + for (int py = 0; py < h; py += ih) + { + const int dh = (py + ih >= h) ? h - py : ih; + int dstY = py + yOffset; + int y2 = srcY; + int h2 = dh; + if (y2 < 0) + { + h2 += y2; + dstY -= static_cast(y2); + y2 = 0; + } + const int maxh = src->h - y2; + if (maxh < h2) + h2 = maxh; + + int dy = clipY - dstY; + if (dy > 0) + { + h2 -= dy; + dstY += static_cast(dy); + y2 += dy; + } + dy = dstY + h2 - clipY - clip->h; + if (dy > 0) + h2 -= dy; + + if (h2 > 0) + { + for (int px = 0; px < w; px += iw) + { + const int dw = (px + iw >= w) ? w - px : iw; + int dstX = px + xOffset; + int x2 = srcX; + int w2 = dw; + if (x2 < 0) + { + w2 += x2; + dstX -= static_cast(x2); + x2 = 0; + } + const int maxw = src->w - x2; + if (maxw < w2) + w2 = maxw; + + int dx = clipX - dstX; + if (dx > 0) + { + w2 -= dx; + dstX += static_cast(dx); + x2 += dx; + } + dx = dstX + w2 - clipX - clip->w; + if (dx > 0) + w2 -= dx; + + if (w2 > 0) + { + SDL_Rect srcRect = + { + static_cast(x2), + static_cast(y2), + static_cast(w2), + static_cast(h2) + }; + + SDL_Rect dstRect = + { + static_cast(dstX), + static_cast(dstY), + static_cast(w2), + static_cast(h2) + }; + + SDL_LowerBlit(src, &srcRect, mWindow, &dstRect); + } + +// SDL_BlitSurface(image->mSDLSurface, &srcRect, mWindow, &dstRect); + } + } + } +} + +void SDLGraphics::completeCache() +{ +} + void SDLGraphics::drawPattern(const Image *const image, const int x, const int y, const int w, const int h) diff --git a/src/render/sdlgraphics.h b/src/render/sdlgraphics.h index b88a47dc4..aa7a250f8 100644 --- a/src/render/sdlgraphics.h +++ b/src/render/sdlgraphics.h @@ -139,6 +139,15 @@ class SDLGraphics final : public Graphics const int width, const int height, const bool useColor) override final; + void drawImageCached(const Image *const image, + int x, int y) override final; + + void drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) override final; + + void completeCache() override final; + protected: int SDL_FakeUpperBlit(const SDL_Surface *const src, SDL_Rect *const srcrect, diff --git a/src/render/surfacegraphics.cpp b/src/render/surfacegraphics.cpp index 879d44f60..db2722164 100644 --- a/src/render/surfacegraphics.cpp +++ b/src/render/surfacegraphics.cpp @@ -80,3 +80,41 @@ bool SurfaceGraphics::drawImage2(const Image *const image, int srcX, int srcY, } #endif } + +void SurfaceGraphics::drawImageCached(const Image *const image, + int x, int y) +{ + FUNC_BLOCK("Graphics::drawImageCached", 1) + // Check that preconditions for blitting are met. + if (!mTarget || !image || !image->mSDLSurface) + return; + + const SDL_Rect &rect = image->mBounds; + + SDL_Rect dstRect; + SDL_Rect srcRect; + dstRect.x = static_cast(x); + dstRect.y = static_cast(y); + srcRect.x = static_cast(rect.x); + srcRect.y = static_cast(rect.y); + srcRect.w = static_cast(rect.w); + srcRect.h = static_cast(rect.h); + +#ifdef USE_SDL2 + SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect); +#else + if (mBlitMode == BLIT_NORMAL) + { + SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect); + } + else + { + SurfaceImageHelper::combineSurface(image->mSDLSurface, &srcRect, + mTarget, &dstRect); + } +#endif +} + +void SurfaceGraphics::completeCache() +{ +} diff --git a/src/render/surfacegraphics.h b/src/render/surfacegraphics.h index b33fa0d63..6a2a7f3cb 100644 --- a/src/render/surfacegraphics.h +++ b/src/render/surfacegraphics.h @@ -188,6 +188,16 @@ class SurfaceGraphics final : public Graphics const int width, const int height, const bool useColor) override final; + void drawImageCached(const Image *const image, + int x, int y) override final; + + void drawPatternCached(const Image *const image, + const int x, const int y, + const int w, const int h) override final + { } + + void completeCache() override final; + protected: BlitMode mBlitMode; SDL_Surface *mTarget; -- cgit v1.2.3-60-g2f50