From 04916c1b451e4400a496ae210b3faa10154c65ac Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 21 Nov 2012 21:13:31 +0300 Subject: Add batch drawing for any images. Add this drawing to Button. --- src/client.cpp | 7 +- src/graphics.cpp | 203 ++++++++++++++++++++++++++++++++++++++- src/graphics.h | 35 +++++++ src/graphicsvertexes.cpp | 27 ++++++ src/graphicsvertexes.h | 22 +++++ src/gui/widgets/button.cpp | 65 ++++++++----- src/gui/widgets/button.h | 4 +- src/gui/widgets/widget2.h | 1 + src/mobileopenglgraphics.cpp | 183 ++++++++++++++++++++++++++++++++++++ src/mobileopenglgraphics.h | 20 ++++ src/normalopenglgraphics.cpp | 219 +++++++++++++++++++++++++++++++++++++++++++ src/normalopenglgraphics.h | 20 ++++ src/safeopenglgraphics.cpp | 6 ++ src/safeopenglgraphics.h | 3 + 14 files changed, 783 insertions(+), 32 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 0ec0647cb..6ea0ad11f 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -147,6 +147,7 @@ UserPalette *userPalette = nullptr; Graphics *mainGraphics = nullptr; Sound sound; +int openGLMode = 0; static uint32_t nextTick(uint32_t interval, void *param A_UNUSED); static uint32_t nextSecond(uint32_t interval, void *param A_UNUSED); @@ -538,12 +539,14 @@ void Client::gameInit() #endif #ifdef USE_OPENGL + openGLMode = config.getIntValue("opengl"); OpenGLImageHelper::setBlur(config.getBoolValue("blur")); SDLImageHelper::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache") - && !config.getIntValue("opengl")); + && !openGLMode); ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f - || config.getIntValue("opengl")); + || openGLMode); #else + openGLMode = 0; SDLImageHelper::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache")); ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f); #endif diff --git a/src/graphics.cpp b/src/graphics.cpp index 16a1de4a2..ec1de72e4 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -590,7 +590,6 @@ void Graphics::drawImageRect(const int x, const int y, right->getWidth(), h - top->getHeight() - bottom->getHeight()); } - // Draw the corners if (drawMain) { @@ -739,6 +738,67 @@ bool Graphics::calcImageRect(GraphicsVertexes *const vert, return 0; } +bool Graphics::calcImageRect(ImageVertexes *const vert, + const int x, const int y, + const int w, const int h, + const Image *const topLeft, + const Image *const topRight, + const Image *const bottomLeft, + const Image *const bottomRight, + const Image *const top, + const Image *const right, + const Image *const bottom, + const Image *const left, + const Image *const center) +{ + if (!vert) + return false; + + BLOCK_START("Graphics::calcImageRect") + const bool drawMain = center && topLeft && topRight + && bottomLeft && bottomRight; + +// pushClipArea(gcn::Rectangle(x, y, w, h)); + + // Draw the center area + if (center && drawMain) + { + calcImagePattern(vert, center, + topLeft->getWidth() + x, topLeft->getHeight() + y, + w - topLeft->getWidth() - topRight->getWidth(), + h - topLeft->getHeight() - bottomLeft->getHeight()); + } + // Draw the sides + if (top && left && bottom && right) + { + calcImagePattern(vert, top, + x + left->getWidth(), y, + w - left->getWidth() - right->getWidth(), top->getHeight()); + calcImagePattern(vert, bottom, + x + left->getWidth(), y + h - bottom->getHeight(), + w - left->getWidth() - right->getWidth(), + bottom->getHeight()); + calcImagePattern(vert, left, + x, y + top->getHeight(), + left->getWidth(), + h - top->getHeight() - bottom->getHeight()); + calcImagePattern(vert, right, + x + w - right->getWidth(), y + top->getHeight(), + right->getWidth(), + h - top->getHeight() - bottom->getHeight()); + } + + calcTile(vert, topLeft, x, y); + calcTile(vert, topRight, x + w - topRight->getWidth(), y); + calcTile(vert, bottomLeft, x, y + h - bottomLeft->getHeight()); + calcTile(vert, bottomRight, x + w - bottomRight->getWidth(), + y + h - bottomRight->getHeight()); + +// popClipArea(); + BLOCK_END("Graphics::calcImageRect") + return 0; +} + void Graphics::calcImagePattern(GraphicsVertexes* const vert, const Image *const image, const int x, const int y, @@ -792,10 +852,119 @@ void Graphics::calcImagePattern(GraphicsVertexes* const vert, vert->incPtr(1); } -void Graphics::calcTile(ImageVertexes *const vert A_UNUSED, - const Image *const image A_UNUSED, - int x A_UNUSED, int y A_UNUSED) const +void Graphics::calcImagePattern(ImageVertexes* const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) const +{ + // Check that preconditions for blitting are met. + if (!vert || !mTarget || !image || !image->mSDLSurface) + return; + + const int iw = image->mBounds.w; + const int ih = image->mBounds.h; + + if (iw == 0 || ih == 0) + return; + + for (int py = 0; py < h; py += ih) // Y position on pattern plane + { + const int dh = (py + ih >= h) ? h - py : ih; + const int srcY = image->mBounds.y; + const int dstY = y + py + mClipStack.top().yOffset; + + for (int px = 0; px < w; px += iw) // X position on pattern plane + { + const int dw = (px + iw >= w) ? w - px : iw; + const int srcX = image->mBounds.x; + const int dstX = x + px + mClipStack.top().xOffset; + + DoubleRect *const r = new DoubleRect(); + SDL_Rect &dstRect = r->dst; + SDL_Rect &srcRect = r->src; + dstRect.x = static_cast(dstX); + dstRect.y = static_cast(dstY); + srcRect.x = static_cast(srcX); + srcRect.y = static_cast(srcY); + srcRect.w = static_cast(dw); + srcRect.h = static_cast(dh); + + if (SDL_FakeUpperBlit(image->mSDLSurface, &srcRect, + mTarget, &dstRect) == 1) + { + vert->sdl.push_back(r); + } + } + } +} + +void Graphics::calcImagePattern(ImageCollection* const vertCol, + const Image *const image, + const int x, const int y, + const int w, const int h) const { + ImageVertexes *vert = nullptr; + if (vertCol->currentImage != image) + { + vert = new ImageVertexes(); + vertCol->currentImage = image; + vertCol->currentVert = vert; + vert->image = image; + vertCol->draws.push_back(vert); + } + else + { + vert = vertCol->currentVert; + } + + calcImagePattern(vert, image, x, y, w, h); +} + +void Graphics::calcTile(ImageVertexes *const vert, + const Image *const image, + int x, int y) const +{ + vert->image = image; + calcTile(vert, x, y); +} + +void Graphics::calcTile(ImageCollection *const vertCol, + const Image *const image, + int x, int y) +{ + if (vertCol->currentImage != image) + { + ImageVertexes *const vert = new ImageVertexes(); + vertCol->currentImage = image; + vertCol->currentVert = vert; + vert->image = image; + vertCol->draws.push_back(vert); + calcTile(vert, x, y); + } + else + { + calcTile(vertCol->currentVert, x, y); + } +} + +void Graphics::drawTile(const ImageCollection *const vertCol) +{ + const ImageVertexesVector &draws = vertCol->draws; + const ImageCollectionCIter it_end = draws.end(); + for (ImageCollectionCIter it = draws.begin(); it != it_end; ++ it) + { + const ImageVertexes *const vert = *it; + const Image *const img = vert->image; + const DoubleRects *const rects = &vert->sdl; + DoubleRects::const_iterator it2 = rects->begin(); + const DoubleRects::const_iterator it2_end = rects->end(); + while (it2 != it2_end) + { + SDL_LowerBlit(img->mSDLSurface, &(*it2)->src, + mTarget, &(*it2)->dst); + ++ it2; + } + } } void Graphics::calcTile(ImageVertexes *const vert, int x, int y) const @@ -901,6 +1070,32 @@ bool Graphics::calcWindow(GraphicsVertexes *const vert, imgRect.grid[4]); } +bool Graphics::calcWindow(ImageCollection *const vertCol, + const int x, const int y, const int w, const int h, + const ImageRect &imgRect) +{ + ImageVertexes *vert = nullptr; + Image *const image = imgRect.grid[4]; + if (vertCol->currentImage != image) + { + vert = new ImageVertexes(); + vertCol->currentImage = image; + vertCol->currentVert = vert; + vert->image = image; + vertCol->draws.push_back(vert); +// calcTile(vert, x, y); + } + else + { + vert = vertCol->currentVert; + } + + return calcImageRect(vert, x, y, w, h, + imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8], + imgRect.grid[1], imgRect.grid[5], imgRect.grid[7], imgRect.grid[3], + imgRect.grid[4]); +} + int Graphics::SDL_FakeUpperBlit(const SDL_Surface *const src, SDL_Rect *const srcrect, const SDL_Surface *const dst, diff --git a/src/graphics.h b/src/graphics.h index 7a5dc41a5..141de7456 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -29,6 +29,7 @@ class GraphicsVertexes; class Image; +class ImageCollection; class ImageVertexes; class MapLayer; @@ -211,11 +212,34 @@ class Graphics : public gcn::SDLGraphics const Image *const left, const Image *const center); + virtual bool calcImageRect(ImageVertexes *const vert, + const int x, const int y, + const int w, const int h, + const Image *const topLeft, + const Image *const topRight, + const Image *const bottomLeft, + const Image *const bottomRight, + const Image *const top, + const Image *const right, + const Image *const bottom, + const Image *const left, + const Image *const center); + virtual void calcImagePattern(GraphicsVertexes *const vert, const Image *const image, const int x, const int y, const int w, const int h) const; + virtual void calcImagePattern(ImageVertexes *const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) const; + + virtual void calcImagePattern(ImageCollection *const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) const; + virtual void calcTile(ImageVertexes *const vert, const Image *const image, int x, int y) const; @@ -223,6 +247,12 @@ class Graphics : public gcn::SDLGraphics virtual void drawTile(const ImageVertexes *const vert); + virtual void drawTile(const ImageCollection *const vertCol); + + virtual void calcTile(ImageCollection *const vertCol, + const Image *const image, + int x, int y); + virtual void drawImageRect2(GraphicsVertexes *const vert, const ImageRect &imgRect); @@ -233,6 +263,11 @@ class Graphics : public gcn::SDLGraphics const int x, const int y, const int w, const int h, const ImageRect &imgRect); + virtual bool calcWindow(ImageCollection *const vertCol, + const int x, const int y, + const int w, const int h, + const ImageRect &imgRect); + /** * Draws a rectangle using images. 4 corner images, 4 side images and 1 * image for the inside. diff --git a/src/graphicsvertexes.cpp b/src/graphicsvertexes.cpp index 3574ffe27..3ad522d79 100644 --- a/src/graphicsvertexes.cpp +++ b/src/graphicsvertexes.cpp @@ -286,3 +286,30 @@ ImageVertexes::~ImageVertexes() delete_all(sdl); sdl.clear(); } + +ImageCollection::ImageCollection() : +#ifdef USE_OPENGL + currentGLImage(0), +#endif + currentImage(nullptr), + currentVert(nullptr) +{ + +} + +ImageCollection::~ImageCollection() +{ + clear(); +} + +void ImageCollection::clear() +{ +#ifdef USE_OPENGL + currentGLImage = 0; +#endif + currentImage = nullptr; + currentVert = nullptr; + + delete_all(draws); + draws.clear(); +} diff --git a/src/graphicsvertexes.h b/src/graphicsvertexes.h index cce9491c1..8a8c1133e 100644 --- a/src/graphicsvertexes.h +++ b/src/graphicsvertexes.h @@ -154,6 +154,28 @@ class ImageVertexes final #endif }; +typedef std::vector ImageVertexesVector; +typedef ImageVertexesVector::const_iterator ImageCollectionCIter; + +class ImageCollection final +{ + public: + ImageCollection(); + + ~ImageCollection(); + + void clear(); + +#ifdef USE_OPENGL + GLuint currentGLImage; +#endif + const Image *currentImage; + + ImageVertexes *currentVert; + + ImageVertexesVector draws; +}; + class GraphicsVertexes final { public: diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index 5a12893a6..5de5f01b5 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -65,7 +65,7 @@ Button::Button(const Widget2 *const widget) : gcn::WidgetListener(), mDescription(""), mClickCount(0), mTag(0), - mVertexes(new GraphicsVertexes()), + mVertexes2(new ImageCollection()), mRedraw(true), mMode(0), mXOffset(0), @@ -90,7 +90,7 @@ Button::Button(const Widget2 *const widget, mDescription(""), mClickCount(0), mTag(0), - mVertexes(new GraphicsVertexes()), + mVertexes2(new ImageCollection()), mRedraw(true), mMode(0), mXOffset(0), @@ -121,7 +121,7 @@ Button::Button(const Widget2 *const widget, mDescription(""), mClickCount(0), mTag(0), - mVertexes(new GraphicsVertexes()), + mVertexes2(new ImageCollection()), mRedraw(true), mMode(0), mXOffset(0), @@ -152,7 +152,7 @@ Button::Button(const Widget2 *const widget, const std::string &imageName, mDescription(""), mClickCount(0), mTag(0), - mVertexes(new GraphicsVertexes()), + mVertexes2(new ImageCollection()), mRedraw(true), mMode(0), mXOffset(0), @@ -210,8 +210,8 @@ Button::~Button() for (int mode = 0; mode < BUTTON_COUNT; mode ++) theme->unload(button[mode]); } - delete mVertexes; - mVertexes = nullptr; + delete mVertexes2; + mVertexes2 = nullptr; if (mImageSet) { mImageSet->decRef(); @@ -326,18 +326,6 @@ void Button::draw(gcn::Graphics *graphics) } } - if (recalc) - { - mRedraw = false; - mMode = mode; - g2->calcWindow(mVertexes, 0, 0, getWidth(), getHeight(), - skin->getBorder()); - } - - g2->drawImageRect2(mVertexes, skin->getBorder()); - -// g2->drawImageRect(0, 0, getWidth(), getHeight(), button[mode]); - const int padding = skin->getPadding(); const int spacing = skin->getOption("spacing"); @@ -401,18 +389,47 @@ void Button::draw(gcn::Graphics *graphics) graphics->setFont(getFont()); - if (isPressed()) + if (openGLMode != 2) { - if (mImages) - g2->drawImage(mImages[mode], imageX + 1, imageY + 1); - g2->drawText(getCaption(), textX + 1, textY + 1, getAlignment()); + if (recalc) + { + mRedraw = false; + mMode = mode; + mVertexes2->clear(); + g2->calcWindow(mVertexes2, 0, 0, getWidth(), getHeight(), + skin->getBorder()); + + if (mImages) + { + if (isPressed()) + { + g2->calcTile(mVertexes2, mImages[mode], + imageX + 1, imageY + 1); + } + else + { + g2->calcTile(mVertexes2, mImages[mode], imageX, imageY); + } + } + } + g2->drawTile(mVertexes2); } else { + g2->drawImageRect(0, 0, getWidth(), getHeight(), skin->getBorder()); if (mImages) - g2->drawImage(mImages[mode], imageX, imageY); - g2->drawText(getCaption(), textX, textY, getAlignment()); + { + if (isPressed()) + g2->drawImage(mImages[mode], imageX + 1, imageY + 1); + else + g2->drawImage(mImages[mode], imageX, imageY); + } } + + if (isPressed()) + g2->drawText(getCaption(), textX + 1, textY + 1, getAlignment()); + else + g2->drawText(getCaption(), textX, textY, getAlignment()); BLOCK_END("Button::draw") } diff --git a/src/gui/widgets/button.h b/src/gui/widgets/button.h index 25fa0da02..3e84eeafe 100644 --- a/src/gui/widgets/button.h +++ b/src/gui/widgets/button.h @@ -31,8 +31,8 @@ #include "localconsts.h" -class GraphicsVertexes; class Image; +class ImageCollection; class ImageSet; class ImageRect; class Skin; @@ -147,7 +147,7 @@ class Button final : public gcn::Button, std::string mDescription; unsigned mClickCount; int mTag; - GraphicsVertexes *mVertexes; + ImageCollection *mVertexes2; bool mRedraw; int mMode; int mXOffset; diff --git a/src/gui/widgets/widget2.h b/src/gui/widgets/widget2.h index 3b4060899..f2eb9bbb1 100644 --- a/src/gui/widgets/widget2.h +++ b/src/gui/widgets/widget2.h @@ -84,4 +84,5 @@ class Widget2 int mPaletteOffset; }; +extern int openGLMode; #endif diff --git a/src/mobileopenglgraphics.cpp b/src/mobileopenglgraphics.cpp index 52e013f41..92afbc741 100644 --- a/src/mobileopenglgraphics.cpp +++ b/src/mobileopenglgraphics.cpp @@ -654,6 +654,163 @@ void MobileOpenGLGraphics::calcImagePattern(GraphicsVertexes *const vert, vert->incPtr(1); } +void MobileOpenGLGraphics::calcImagePattern(ImageVertexes *const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) const +{ + if (!image) + return; + + const int srcX = image->mBounds.x; + const int srcY = image->mBounds.y; + + const int iw = image->mBounds.w; + const int ih = image->mBounds.h; + + if (iw == 0 || ih == 0) + return; + + const float tw = static_cast(image->mTexWidth); + const float th = static_cast(image->mTexHeight); + + const unsigned int vLimit = mMaxVertices * 4; + + NormalOpenGLGraphicsVertexes &ogl = vert->ogl; + unsigned int vp = ogl.continueVp(); + + // Draw a set of textured rectangles +// if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + float texX1 = static_cast(srcX) / tw; + float texY1 = static_cast(srcY) / th; + + GLfloat *floatTexArray = ogl.continueFloatTexArray(); + GLshort *shortVertArray = ogl.continueShortVertArray(); + + 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; + + float texX2 = static_cast(srcX + width) / tw; + float texY2 = static_cast(srcY + height) / th; + + floatTexArray[vp + 0] = texX1; + floatTexArray[vp + 1] = texY1; + + floatTexArray[vp + 2] = texX2; + floatTexArray[vp + 3] = texY1; + + floatTexArray[vp + 4] = texX2; + floatTexArray[vp + 5] = texY2; + + floatTexArray[vp + 6] = texX1; + floatTexArray[vp + 7] = texY1; + + floatTexArray[vp + 8] = texX1; + floatTexArray[vp + 9] = texY2; + + floatTexArray[vp + 10] = texX2; + floatTexArray[vp + 11] = texY2; + + + shortVertArray[vp + 0] = dstX; + shortVertArray[vp + 1] = dstY; + + shortVertArray[vp + 2] = dstX + width; + shortVertArray[vp + 3] = dstY; + + shortVertArray[vp + 4] = dstX + width; + shortVertArray[vp + 5] = dstY + height; + + shortVertArray[vp + 6] = dstX; + shortVertArray[vp + 7] = dstY; + + shortVertArray[vp + 8] = dstX; + shortVertArray[vp + 9] = dstY + height; + + shortVertArray[vp + 10] = dstX + width; + shortVertArray[vp + 11] = dstY + height; + + vp += 12; + if (vp >= vLimit) + { + floatTexArray = ogl.switchFloatTexArray(); + shortVertArray = ogl.switchShortVertArray(); + ogl.switchVp(vp); + vp = 0; + } + } + } + } + ogl.switchVp(vp); +} + +void MobileOpenGLGraphics::calcTile(ImageCollection *const vertCol, + const Image *const image, + int x, int y) +{ + if (vertCol->currentGLImage != image->mGLImage) + { + ImageVertexes *const vert = new ImageVertexes(); + vertCol->currentGLImage = image->mGLImage; + vertCol->currentVert = vert; + vert->image = image; + vertCol->draws.push_back(vert); + calcTile(vert, image, x, y); + } + else + { + calcTile(vertCol->currentVert, image, x, y); + } +} + +void MobileOpenGLGraphics::drawTile(const ImageCollection *const vertCol) +{ + const ImageVertexesVector &draws = vertCol->draws; + const ImageCollectionCIter it_end = draws.end(); + for (ImageCollectionCIter it = draws.begin(); it != it_end; ++ it) + { + const ImageVertexes *const vert = *it; + const Image *const image = vert->image; + + setColorAlpha(image->mAlpha); +#ifdef DEBUG_BIND_TEXTURE + debugBindTexture(image); +#endif + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + setTexturingAndBlending(true); + drawVertexes(vert->ogl); + } +} + +void MobileOpenGLGraphics::calcImagePattern(ImageCollection* const vertCol, + const Image *const image, + const int x, const int y, + const int w, const int h) const +{ + ImageVertexes *vert = nullptr; + if (vertCol->currentGLImage != image->mGLImage) + { + vert = new ImageVertexes(); + vertCol->currentGLImage = image->mGLImage; + vertCol->currentVert = vert; + vert->image = image; + vertCol->draws.push_back(vert); + } + else + { + vert = vertCol->currentVert; + } + + calcImagePattern(vert, image, x, y, w, h); +} + void MobileOpenGLGraphics::calcTile(ImageVertexes *const vert, const Image *const image, int dstX, int dstY) const @@ -755,6 +912,32 @@ void MobileOpenGLGraphics::drawTile(const ImageVertexes *const vert) drawVertexes(vert->ogl); } +bool MobileOpenGLGraphics::calcWindow(ImageCollection *const vertCol, + const int x, const int y, + const int w, const int h, + const ImageRect &imgRect) +{ + ImageVertexes *vert = nullptr; + Image *const image = imgRect.grid[4]; + if (vertCol->currentGLImage != image->mGLImage) + { + vert = new ImageVertexes(); + vertCol->currentGLImage = image->mGLImage; + vertCol->currentVert = vert; + vert->image = image; + vertCol->draws.push_back(vert); + } + else + { + vert = vertCol->currentVert; + } + + return calcImageRect(vert, x, y, w, h, + imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8], + imgRect.grid[1], imgRect.grid[5], imgRect.grid[7], imgRect.grid[3], + imgRect.grid[4]); +} + void MobileOpenGLGraphics::updateScreen() { BLOCK_START("Graphics::updateScreen") diff --git a/src/mobileopenglgraphics.h b/src/mobileopenglgraphics.h index 78d24d5fc..ad630c6b7 100644 --- a/src/mobileopenglgraphics.h +++ b/src/mobileopenglgraphics.h @@ -95,14 +95,34 @@ class MobileOpenGLGraphics final : public Graphics const int x, const int y, const int w, const int h) const override; + void calcImagePattern(ImageVertexes *const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) const override; + + void calcImagePattern(ImageCollection *const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) const override; + void calcTile(ImageVertexes *const vert, const Image *const image, int x, int y) const override; + void drawTile(const ImageCollection *const vertCol); + + void calcTile(ImageCollection *const vertCol, + const Image *const image, int x, int y) override; + void drawTile(const ImageVertexes *const vert) override; void drawImagePattern2(const GraphicsVertexes *const vert, const Image *const image) override; + bool calcWindow(ImageCollection *const vertCol, + const int x, const int y, + const int w, const int h, + const ImageRect &imgRect); + void updateScreen() override; void _beginDraw(); diff --git a/src/normalopenglgraphics.cpp b/src/normalopenglgraphics.cpp index 11cc8ab5f..f7ca7b802 100644 --- a/src/normalopenglgraphics.cpp +++ b/src/normalopenglgraphics.cpp @@ -823,6 +823,199 @@ void NormalOpenGLGraphics::calcImagePattern(GraphicsVertexes *const vert, vert->incPtr(1); } +void NormalOpenGLGraphics::calcImagePattern(ImageVertexes* const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) const +{ + if (!image) + return; + + const int srcX = image->mBounds.x; + const int srcY = image->mBounds.y; + + const int iw = image->mBounds.w; + const int ih = image->mBounds.h; + + if (iw == 0 || ih == 0) + return; + + const float tw = static_cast(image->mTexWidth); + const float th = static_cast(image->mTexHeight); + + const unsigned int vLimit = mMaxVertices * 4; + + NormalOpenGLGraphicsVertexes &ogl = vert->ogl; + unsigned int vp = ogl.continueVp(); + + // Draw a set of textured rectangles + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + float texX1 = static_cast(srcX) / tw; + float texY1 = static_cast(srcY) / th; + + GLfloat *floatTexArray = ogl.continueFloatTexArray(); + GLint *intVertArray = ogl.continueIntVertArray(); + + 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; + + float texX2 = static_cast(srcX + width) / tw; + float texY2 = static_cast(srcY + height) / th; + + floatTexArray[vp + 0] = texX1; + floatTexArray[vp + 1] = texY1; + + floatTexArray[vp + 2] = texX2; + floatTexArray[vp + 3] = texY1; + + floatTexArray[vp + 4] = texX2; + floatTexArray[vp + 5] = texY2; + + floatTexArray[vp + 6] = texX1; + floatTexArray[vp + 7] = texY2; + + intVertArray[vp + 0] = dstX; + intVertArray[vp + 1] = dstY; + + intVertArray[vp + 2] = dstX + width; + intVertArray[vp + 3] = dstY; + + intVertArray[vp + 4] = dstX + width; + intVertArray[vp + 5] = dstY + height; + + intVertArray[vp + 6] = dstX; + intVertArray[vp + 7] = dstY + height; + + vp += 8; + if (vp >= vLimit) + { + floatTexArray = ogl.switchFloatTexArray(); + intVertArray = ogl.switchIntVertArray(); + ogl.switchVp(vp); + vp = 0; + } + } + } + } + else + { + GLint *intTexArray = ogl.continueIntTexArray(); + GLint *intVertArray = ogl.continueIntVertArray(); + + 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; + + intTexArray[vp + 0] = srcX; + intTexArray[vp + 1] = srcY; + + intTexArray[vp + 2] = srcX + width; + intTexArray[vp + 3] = srcY; + + intTexArray[vp + 4] = srcX + width; + intTexArray[vp + 5] = srcY + height; + + intTexArray[vp + 6] = srcX; + intTexArray[vp + 7] = srcY + height; + + intVertArray[vp + 0] = dstX; + intVertArray[vp + 1] = dstY; + + intVertArray[vp + 2] = dstX + width; + intVertArray[vp + 3] = dstY; + + intVertArray[vp + 4] = dstX + width; + intVertArray[vp + 5] = dstY + height; + + intVertArray[vp + 6] = dstX; + intVertArray[vp + 7] = dstY + height; + + vp += 8; + if (vp >= vLimit) + { + intTexArray = ogl.switchIntTexArray(); + intVertArray = ogl.switchIntVertArray(); + ogl.switchVp(vp); + vp = 0; + } + } + } + } + ogl.switchVp(vp); +} + +void NormalOpenGLGraphics::calcTile(ImageCollection *const vertCol, + const Image *const image, + int x, int y) +{ + if (vertCol->currentGLImage != image->mGLImage) + { + ImageVertexes *const vert = new ImageVertexes(); + vertCol->currentGLImage = image->mGLImage; + vertCol->currentVert = vert; + vert->image = image; + vertCol->draws.push_back(vert); + calcTile(vert, image, x, y); + } + else + { + calcTile(vertCol->currentVert, image, x, y); + } +} + +void NormalOpenGLGraphics::drawTile(const ImageCollection *const vertCol) +{ + const ImageVertexesVector &draws = vertCol->draws; + const ImageCollectionCIter it_end = draws.end(); + for (ImageCollectionCIter it = draws.begin(); it != it_end; ++ it) + { + const ImageVertexes *const vert = *it; + const Image *const image = vert->image; + + setColorAlpha(image->mAlpha); +#ifdef DEBUG_BIND_TEXTURE + debugBindTexture(image); +#endif + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + setTexturingAndBlending(true); + drawVertexes(vert->ogl); + } +} + +void NormalOpenGLGraphics::calcImagePattern(ImageCollection* const vertCol, + const Image *const image, + const int x, const int y, + const int w, const int h) const +{ + ImageVertexes *vert = nullptr; + if (vertCol->currentGLImage != image->mGLImage) + { + vert = new ImageVertexes(); + vertCol->currentGLImage = image->mGLImage; + vertCol->currentVert = vert; + vert->image = image; + vertCol->draws.push_back(vert); + } + else + { + vert = vertCol->currentVert; + } + + calcImagePattern(vert, image, x, y, w, h); +} + void NormalOpenGLGraphics::calcTile(ImageVertexes *const vert, const Image *const image, int dstX, int dstY) const @@ -950,6 +1143,32 @@ void NormalOpenGLGraphics::drawTile(const ImageVertexes *const vert) drawVertexes(vert->ogl); } +bool NormalOpenGLGraphics::calcWindow(ImageCollection *const vertCol, + const int x, const int y, + const int w, const int h, + const ImageRect &imgRect) +{ + ImageVertexes *vert = nullptr; + Image *const image = imgRect.grid[4]; + if (vertCol->currentGLImage != image->mGLImage) + { + vert = new ImageVertexes(); + vertCol->currentGLImage = image->mGLImage; + vertCol->currentVert = vert; + vert->image = image; + vertCol->draws.push_back(vert); + } + else + { + vert = vertCol->currentVert; + } + + return calcImageRect(vert, x, y, w, h, + imgRect.grid[0], imgRect.grid[2], imgRect.grid[6], imgRect.grid[8], + imgRect.grid[1], imgRect.grid[5], imgRect.grid[7], imgRect.grid[3], + imgRect.grid[4]); +} + void NormalOpenGLGraphics::updateScreen() { BLOCK_START("Graphics::updateScreen") diff --git a/src/normalopenglgraphics.h b/src/normalopenglgraphics.h index 0c5bb40ac..2c70a0fbe 100644 --- a/src/normalopenglgraphics.h +++ b/src/normalopenglgraphics.h @@ -95,14 +95,34 @@ class NormalOpenGLGraphics final : public Graphics const int x, const int y, const int w, const int h) const override; + void calcImagePattern(ImageVertexes* const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) const override; + + void calcImagePattern(ImageCollection* const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) const override; + void calcTile(ImageVertexes *const vert, const Image *const image, int x, int y) const override; + void calcTile(ImageCollection *const vertCol, + const Image *const image, int x, int y) override; + + void drawTile(const ImageCollection *const vertCol) override; + void drawTile(const ImageVertexes *const vert) override; void drawImagePattern2(const GraphicsVertexes *const vert, const Image *const image) override; + bool calcWindow(ImageCollection *const vertCol, + const int x, const int y, + const int w, const int h, + const ImageRect &imgRect) override; + void updateScreen() override; void _beginDraw(); diff --git a/src/safeopenglgraphics.cpp b/src/safeopenglgraphics.cpp index 6142627f1..6b6c80116 100644 --- a/src/safeopenglgraphics.cpp +++ b/src/safeopenglgraphics.cpp @@ -353,6 +353,12 @@ bool SafeOpenGLGraphics::calcImageRect(GraphicsVertexes *const vert, return true; } +void SafeOpenGLGraphics::calcTile(ImageCollection *const vertCol A_UNUSED, + const Image *const image A_UNUSED, + int x A_UNUSED, int y A_UNUSED) +{ +} + void SafeOpenGLGraphics::calcTile(ImageVertexes *const vert A_UNUSED, const Image *const image A_UNUSED, int x A_UNUSED, int y A_UNUSED) const diff --git a/src/safeopenglgraphics.h b/src/safeopenglgraphics.h index 1b84689df..cd79f213f 100644 --- a/src/safeopenglgraphics.h +++ b/src/safeopenglgraphics.h @@ -102,6 +102,9 @@ class SafeOpenGLGraphics final : public Graphics void calcTile(ImageVertexes *const vert, const Image *const image, int x, int y) const override; + void calcTile(ImageCollection *const vertCol, + const Image *const image, int x, int y) override; + void drawTile(const ImageVertexes *const vert) override; void updateScreen() override; -- cgit v1.2.3-70-g09d2