From a7768a7d85ecab6ee3a7184776d21b084e97831e Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Wed, 7 Mar 2018 13:36:42 -0500 Subject: [PATCH 1/3] fixes #4722: fix drawing of widget borders Co-Authored-By: Forgon2100 --- src/intimage.cpp | 1 - src/intimage.h | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/intimage.cpp b/src/intimage.cpp index 6fcf94f55c9..f9c1d7bd42a 100644 --- a/src/intimage.cpp +++ b/src/intimage.cpp @@ -27,7 +27,6 @@ #include "lib/framework/frame.h" #include "lib/framework/frameresource.h" #include "lib/ivis_opengl/bitimage.h" -#include "lib/ivis_opengl/pieblitfunc.h" #include "lib/ivis_opengl/piepalette.h" #include "lib/ivis_opengl/piestate.h" diff --git a/src/intimage.h b/src/intimage.h index 0b80b6d1b6e..a59db3b6d3b 100644 --- a/src/intimage.h +++ b/src/intimage.h @@ -22,6 +22,7 @@ #include "intfac.h" // Interface image id's. #include "lib/widget/listwidget.h" +#include "lib/ivis_opengl/pieblitfunc.h" #define FILLRED 16 #define FILLGREEN 16 @@ -53,6 +54,6 @@ extern IMAGEFILE *IntImages; //< All the 2d graphics for the user interface. bool imageInitBitmaps(); /** Draws a transparent window. */ -void RenderWindowFrame(FRAMETYPE frame, uint32_t x, uint32_t y, uint32_t Width, uint32_t Heig, const glm::mat4 &modelViewProjection = glm::mat4()); +void RenderWindowFrame(FRAMETYPE frame, uint32_t x, uint32_t y, uint32_t Width, uint32_t Heig, const glm::mat4 &modelViewProjection = defaultProjectionMatrix()); #endif From a8b7495ca49d085877dcf84440a8f3890a7c295e Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Fri, 9 Mar 2018 15:28:40 -0500 Subject: [PATCH 2/3] fixes #4722: Frame corners should respect the input modelViewProjectionMatrix This fixes the drawing of the radar frame corners. --- src/intimage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/intimage.cpp b/src/intimage.cpp index f9c1d7bd42a..8dfbcd6b659 100644 --- a/src/intimage.cpp +++ b/src/intimage.cpp @@ -181,28 +181,28 @@ void RenderWindowFrame(FRAMETYPE frame, UDWORD x, UDWORD y, UDWORD Width, UDWORD { WTopLeft = (SWORD)iV_GetImageWidth(IntImages, Frame->TopLeft); HTopLeft = (SWORD)iV_GetImageHeight(IntImages, Frame->TopLeft); - iV_DrawImage(IntImages, Frame->TopLeft, x, y); + iV_DrawImage(IntImages, Frame->TopLeft, x, y, modelViewProjectionMatrix); } if (Frame->TopRight >= 0) { WTopRight = (SWORD)iV_GetImageWidth(IntImages, Frame->TopRight); HTopRight = (SWORD)iV_GetImageHeight(IntImages, Frame->TopRight); - iV_DrawImage(IntImages, Frame->TopRight, x + Width - WTopRight, y); + iV_DrawImage(IntImages, Frame->TopRight, x + Width - WTopRight, y, modelViewProjectionMatrix); } if (Frame->BottomRight >= 0) { WBottomRight = (SWORD)iV_GetImageWidth(IntImages, Frame->BottomRight); HBottomRight = (SWORD)iV_GetImageHeight(IntImages, Frame->BottomRight); - iV_DrawImage(IntImages, Frame->BottomRight, x + Width - WBottomRight, y + Height - HBottomRight); + iV_DrawImage(IntImages, Frame->BottomRight, x + Width - WBottomRight, y + Height - HBottomRight, modelViewProjectionMatrix); } if (Frame->BottomLeft >= 0) { WBottomLeft = (SWORD)iV_GetImageWidth(IntImages, Frame->BottomLeft); HBottomLeft = (SWORD)iV_GetImageHeight(IntImages, Frame->BottomLeft); - iV_DrawImage(IntImages, Frame->BottomLeft, x, y + Height - HBottomLeft); + iV_DrawImage(IntImages, Frame->BottomLeft, x, y + Height - HBottomLeft, modelViewProjectionMatrix); } if (Frame->TopEdge >= 0) From 82d6be3cd2843db1e40c3be1e170474a1e60b21c Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Sat, 10 Mar 2018 13:46:26 -0500 Subject: [PATCH 3/3] Batch certain repetitive image draw requests --- lib/ivis_opengl/pieblitfunc.cpp | 117 +++++++++++++++++++++++++++----- lib/ivis_opengl/pieblitfunc.h | 60 +++++++++++++++- src/intdisplay.cpp | 18 +++-- src/intimage.cpp | 20 +++--- 4 files changed, 180 insertions(+), 35 deletions(-) diff --git a/lib/ivis_opengl/pieblitfunc.cpp b/lib/ivis_opengl/pieblitfunc.cpp index 8a82011c021..f8e948c421e 100644 --- a/lib/ivis_opengl/pieblitfunc.cpp +++ b/lib/ivis_opengl/pieblitfunc.cpp @@ -51,11 +51,6 @@ static GFX *radarGfx = nullptr; -struct PIERECT ///< Screen rectangle. -{ - float x, y, w, h; -}; - /***************************************************************************/ /* * Static function forward declarations @@ -422,6 +417,52 @@ static void pie_DrawImage(IMAGEFILE *imageFile, int id, Vector2i size, const PIE iv_DrawImageImpl(Vector2f(0.f, 0.f), Vector2f(dest->w, dest->h), Vector2f(tu, tv), Vector2f(su, sv), colour, mvp); } +static void pie_DrawMultipleImages(const std::list& requests) +{ + bool didEnableRect = false; + if (requests.empty()) { return; } + for (auto& request : requests) + { + pie_SetRendMode(request.rendMode); + + // The following is the equivalent of: + // pie_DrawImage(request.imageFile, request.ID, request.size, &request.dest, request.colour, request.modelViewProjection, request.textureInset) + // but is tweaked to use custom implementation of iv_DrawImageImpl that does not disable the shader after every glDrawArrays call. + + ImageDef const &image2 = request.imageFile->imageDefs[request.ID]; + GLuint texPage = request.imageFile->pages[image2.TPageID].id; + GLfloat invTextureSize = 1.f / (float)request.imageFile->pages[image2.TPageID].size; + float tu = (float)(image2.Tu + request.textureInset.x) * invTextureSize; + float tv = (float)(image2.Tv + request.textureInset.y) * invTextureSize; + float su = (float)(request.size.x - (request.textureInset.x * 2)) * invTextureSize; + float sv = (float)(request.size.y - (request.textureInset.y * 2)) * invTextureSize; + + glm::mat4 mvp = request.modelViewProjection * glm::translate((float)request.dest.x, (float)request.dest.y, 0.f); + + pie_SetTexturePage(texPage); + + Vector2f offset = Vector2f(0.f, 0.f); + Vector2f size = Vector2f(request.dest.w, request.dest.h); + Vector2f TextureUV = Vector2f(tu, tv); + Vector2f TextureSize = Vector2f(su, sv); + glm::mat4 transformMat = mvp * glm::translate(offset.x, offset.y, 0.f) * glm::scale(size.x, size.y, 1.f); + + pie_ActivateShader(SHADER_TEXRECT, + transformMat, + TextureUV, + TextureSize, + glm::vec4(request.colour.vector[0] / 255.f, request.colour.vector[1] / 255.f, request.colour.vector[2] / 255.f, request.colour.vector[3] / 255.f), 0); + if (!didEnableRect) + { + enableRect(); + didEnableRect = true; + } + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + disableRect(); + pie_DeactivateShader(); +} + static Vector2i makePieImage(IMAGEFILE *imageFile, unsigned id, PIERECT *dest, int x, int y) { ImageDef const &image = imageFile->imageDefs[id]; @@ -458,7 +499,7 @@ void iV_DrawImage2(const QString &filename, float x, float y, float width, float WZCOL_WHITE, mvp); } -void iV_DrawImage(IMAGEFILE *ImageFile, UWORD ID, int x, int y, const glm::mat4 &modelViewProjection) +void iV_DrawImage(IMAGEFILE *ImageFile, UWORD ID, int x, int y, const glm::mat4 &modelViewProjection, BatchedImageDrawRequests* pBatchedRequests) { if (!assertValidImage(ImageFile, ID)) { @@ -468,9 +509,16 @@ void iV_DrawImage(IMAGEFILE *ImageFile, UWORD ID, int x, int y, const glm::mat4 PIERECT dest; Vector2i pieImage = makePieImage(ImageFile, ID, &dest, x, y); - pie_SetRendMode(REND_ALPHA); - - pie_DrawImage(ImageFile, ID, pieImage, &dest, WZCOL_WHITE, modelViewProjection); + if (pBatchedRequests == nullptr) + { + pie_SetRendMode(REND_ALPHA); + pie_DrawImage(ImageFile, ID, pieImage, &dest, WZCOL_WHITE, modelViewProjection); + } + else + { + pBatchedRequests->queuePieImageDraw(REND_ALPHA, ImageFile, ID, pieImage, dest, WZCOL_WHITE, modelViewProjection); + pBatchedRequests->draw(); // draw only if not deferred + } } void iV_DrawImageTc(Image image, Image imageTc, int x, int y, PIELIGHT colour, const glm::mat4 &modelViewProjection) @@ -491,12 +539,19 @@ void iV_DrawImageTc(Image image, Image imageTc, int x, int y, PIELIGHT colour, c } // Repeat a texture -void iV_DrawImageRepeatX(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Width, const glm::mat4 &modelViewProjection, bool enableHorizontalTilingSeamWorkaround) +void iV_DrawImageRepeatX(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Width, const glm::mat4 &modelViewProjection, bool enableHorizontalTilingSeamWorkaround, BatchedImageDrawRequests *pBatchedRequests) { + static BatchedImageDrawRequests localBatch; + if (pBatchedRequests == nullptr) + { + localBatch.clear(); + pBatchedRequests = &localBatch; + } + assertValidImage(ImageFile, ID); const ImageDef *Image = &ImageFile->imageDefs[ID]; - pie_SetRendMode(REND_OPAQUE); + REND_MODE mode = REND_OPAQUE; PIERECT dest; Vector2i pieImage = makePieImage(ImageFile, ID, &dest, x, y); @@ -516,7 +571,7 @@ void iV_DrawImageRepeatX(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Width for (unsigned hRep = 0; hRep < Width / usableImageWidth; hRep++) { - pie_DrawImage(ImageFile, ID, pieImage, &dest, WZCOL_WHITE, modelViewProjection, Vector2i(imageXInset, 0)); + pBatchedRequests->queuePieImageDraw(mode, ImageFile, ID, pieImage, dest, WZCOL_WHITE, modelViewProjection, Vector2i(imageXInset, 0)); dest.x += usableImageWidth; } @@ -525,16 +580,26 @@ void iV_DrawImageRepeatX(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Width { pieImage.x = hRemainder; dest.w = hRemainder; - pie_DrawImage(ImageFile, ID, pieImage, &dest, WZCOL_WHITE, modelViewProjection, Vector2i(imageXInset, 0)); + pBatchedRequests->queuePieImageDraw(mode, ImageFile, ID, pieImage, dest, WZCOL_WHITE, modelViewProjection, Vector2i(imageXInset, 0)); } + + // draw batched requests (unless batch is deferred) + pBatchedRequests->draw(); } -void iV_DrawImageRepeatY(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Height, const glm::mat4 &modelViewProjection) +void iV_DrawImageRepeatY(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Height, const glm::mat4 &modelViewProjection, BatchedImageDrawRequests* pBatchedRequests) { + static BatchedImageDrawRequests localBatch; + if (pBatchedRequests == nullptr) + { + localBatch.clear(); + pBatchedRequests = &localBatch; + } + assertValidImage(ImageFile, ID); const ImageDef *Image = &ImageFile->imageDefs[ID]; - pie_SetRendMode(REND_OPAQUE); + REND_MODE mode = REND_OPAQUE; PIERECT dest; Vector2i pieImage = makePieImage(ImageFile, ID, &dest, x, y); @@ -543,7 +608,7 @@ void iV_DrawImageRepeatY(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Heigh for (unsigned vRep = 0; vRep < Height / Image->Height; vRep++) { - pie_DrawImage(ImageFile, ID, pieImage, &dest, WZCOL_WHITE, modelViewProjection); + pBatchedRequests->queuePieImageDraw(mode, ImageFile, ID, pieImage, dest, WZCOL_WHITE, modelViewProjection); dest.y += Image->Height; } @@ -552,8 +617,11 @@ void iV_DrawImageRepeatY(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Heigh { pieImage.y = vRemainder; dest.h = vRemainder; - pie_DrawImage(ImageFile, ID, pieImage, &dest, WZCOL_WHITE, modelViewProjection); + pBatchedRequests->queuePieImageDraw(mode, ImageFile, ID, pieImage, dest, WZCOL_WHITE, modelViewProjection); } + + // draw batched requests (unless batch is deferred) + pBatchedRequests->draw(); } bool pie_InitRadar() @@ -614,3 +682,18 @@ glm::mat4 defaultProjectionMatrix() return glm::ortho(0.f, static_cast(w), static_cast(h), 0.f); } + + +void BatchedImageDrawRequests::clear() +{ + ASSERT(_imageDrawRequests.empty(), "Clearing a BatchedImageDrawRequests that isn't empty. Images have not been drawn!"); + _imageDrawRequests.clear(); +} + +bool BatchedImageDrawRequests::draw(bool force /*= false*/) +{ + if (deferRender && !force) { return false; } + pie_DrawMultipleImages(_imageDrawRequests); + _imageDrawRequests.clear(); + return true; +} diff --git a/lib/ivis_opengl/pieblitfunc.h b/lib/ivis_opengl/pieblitfunc.h index 243b1499e65..159c2f64ab4 100644 --- a/lib/ivis_opengl/pieblitfunc.h +++ b/lib/ivis_opengl/pieblitfunc.h @@ -137,13 +137,67 @@ struct PIERECT_DrawRequest PIELIGHT color; }; void pie_DrawMultiRect(std::vector rects, REND_MODE rendermode = REND_OPAQUE); +struct PIERECT ///< Screen rectangle. +{ + float x, y, w, h; +}; +struct PieDrawImageRequest { +public: + PieDrawImageRequest(REND_MODE rendMode, IMAGEFILE *imageFile, int ID, Vector2i size, const PIERECT& dest, PIELIGHT colour, const glm::mat4& modelViewProjection, Vector2i textureInset = Vector2i(0, 0)) + : rendMode(rendMode), + imageFile(imageFile), + ID(ID), + size(size), + dest(dest), + colour(colour), + modelViewProjection(modelViewProjection), + textureInset(textureInset) + { } + +public: + REND_MODE rendMode; + + IMAGEFILE *imageFile; + int ID; + Vector2i size; + const PIERECT dest; + PIELIGHT colour; + glm::mat4 modelViewProjection; + Vector2i textureInset; +}; +struct BatchedImageDrawRequests { +public: + BatchedImageDrawRequests(bool deferRender = false) + : deferRender(deferRender) + { } +public: + void queuePieImageDraw(REND_MODE rendMode, IMAGEFILE *imageFile, int id, Vector2i size, const PIERECT& dest, PIELIGHT colour, const glm::mat4& modelViewProjection, Vector2i textureInset = Vector2i(0, 0)) + { + queuePieImageDraw(PieDrawImageRequest(rendMode, imageFile, id, size, dest, colour, modelViewProjection, textureInset)); + } + void queuePieImageDraw(const PieDrawImageRequest& request) + { + _imageDrawRequests.push_back(request); + } + void queuePieImageDraw(const PieDrawImageRequest&& request) + { + _imageDrawRequests.push_back(std::move(request)); + } + + bool draw(bool force = false); + void clear(); +public: + bool deferRender = false; +private: + std::list _imageDrawRequests; +}; void iV_DrawImage(GLuint TextureID, Vector2i position, Vector2f offset, Vector2i size, float angle, REND_MODE mode, PIELIGHT colour); void iV_DrawImageText(gfx_api::texture& TextureID, Vector2i Position, Vector2f offset, Vector2f size, float angle, REND_MODE mode, PIELIGHT colour); -void iV_DrawImage(IMAGEFILE *ImageFile, UWORD ID, int x, int y, const glm::mat4 &modelViewProjection = defaultProjectionMatrix()); +void iV_DrawImage(IMAGEFILE *ImageFile, UWORD ID, int x, int y, const glm::mat4 &modelViewProjection = defaultProjectionMatrix(), BatchedImageDrawRequests* pBatchedRequests = nullptr); void iV_DrawImage2(const QString &filename, float x, float y, float width = -0.0f, float height = -0.0f); void iV_DrawImageTc(Image image, Image imageTc, int x, int y, PIELIGHT colour, const glm::mat4 &modelViewProjection = defaultProjectionMatrix()); -void iV_DrawImageRepeatX(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Width, const glm::mat4 &modelViewProjection = defaultProjectionMatrix(), bool enableHorizontalTilingSeamWorkaround = false); -void iV_DrawImageRepeatY(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Height, const glm::mat4 &modelViewProjection = defaultProjectionMatrix()); +void iV_DrawImageRepeatX(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Width, const glm::mat4 &modelViewProjection = defaultProjectionMatrix(), bool enableHorizontalTilingSeamWorkaround = false, BatchedImageDrawRequests* pBatchedRequests = nullptr); +void iV_DrawImageRepeatY(IMAGEFILE *ImageFile, UWORD ID, int x, int y, int Height, const glm::mat4 &modelViewProjection = defaultProjectionMatrix(), BatchedImageDrawRequests* pBatchedRequests = nullptr); static inline void iV_DrawImage(Image image, int x, int y) { diff --git a/src/intdisplay.cpp b/src/intdisplay.cpp index 3b2ed2d3599..ad7828c4c0f 100644 --- a/src/intdisplay.cpp +++ b/src/intdisplay.cpp @@ -621,44 +621,48 @@ void intDisplayPowerBar(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset) x0 += iV_GetImageWidth(IntImages, IMAGE_PBAR_TOP); + BatchedImageDrawRequests imageDrawBatch(true); // defer drawing + //fill in the empty section behind text if (textWidth > 0) { - iV_DrawImageRepeatX(IntImages, IMAGE_PBAR_EMPTY, x0 - 1, y0, textWidth + 1, defaultProjectionMatrix(), true); // Overdraw by 1 to reduce seam with left-beginning-piece when scaling + iV_DrawImageRepeatX(IntImages, IMAGE_PBAR_EMPTY, x0 - 1, y0, textWidth + 1, defaultProjectionMatrix(), true, &imageDrawBatch); // Overdraw by 1 to reduce seam with left-beginning-piece when scaling x0 += textWidth; } //draw the left-most beginning tip //to reduce a visible seam when scaling, this must come *after* the empty / text section above - iV_DrawImage(IntImages, IMAGE_PBAR_TOP, top_x0, top_y0); + iV_DrawImage(IntImages, IMAGE_PBAR_TOP, top_x0, top_y0, defaultProjectionMatrix(), &imageDrawBatch); //draw required section if (ManPow > Avail) { //draw the required in red - iV_DrawImageRepeatX(IntImages, IMAGE_PBAR_USED, x0, y0, ManPow, defaultProjectionMatrix(), true); + iV_DrawImageRepeatX(IntImages, IMAGE_PBAR_USED, x0, y0, ManPow, defaultProjectionMatrix(), true, &imageDrawBatch); } else { - iV_DrawImageRepeatX(IntImages, IMAGE_PBAR_REQUIRED, x0, y0, ManPow, defaultProjectionMatrix(), true); + iV_DrawImageRepeatX(IntImages, IMAGE_PBAR_REQUIRED, x0, y0, ManPow, defaultProjectionMatrix(), true, &imageDrawBatch); } x0 += ManPow; //draw the available section if any! if (Avail - ManPow > 0) { - iV_DrawImageRepeatX(IntImages, IMAGE_PBAR_AVAIL, x0, y0, Avail - ManPow, defaultProjectionMatrix(), true); + iV_DrawImageRepeatX(IntImages, IMAGE_PBAR_AVAIL, x0, y0, Avail - ManPow, defaultProjectionMatrix(), true, &imageDrawBatch); x0 += Avail - ManPow; } //fill in the rest with empty section if (Empty > 0) { - iV_DrawImageRepeatX(IntImages, IMAGE_PBAR_EMPTY, x0, y0, Empty + 1, defaultProjectionMatrix(), true); // Overdraw by 1 to reduce seam with right-end-piece when scaling + iV_DrawImageRepeatX(IntImages, IMAGE_PBAR_EMPTY, x0, y0, Empty + 1, defaultProjectionMatrix(), true, &imageDrawBatch); // Overdraw by 1 to reduce seam with right-end-piece when scaling x0 += Empty; } - iV_DrawImage(IntImages, IMAGE_PBAR_BOTTOM, x0, y0); + iV_DrawImage(IntImages, IMAGE_PBAR_BOTTOM, x0, y0, defaultProjectionMatrix(), &imageDrawBatch); + + imageDrawBatch.draw(true); PIELIGHT colour; if (Avail < 0) diff --git a/src/intimage.cpp b/src/intimage.cpp index 8dfbcd6b659..52c8cde4764 100644 --- a/src/intimage.cpp +++ b/src/intimage.cpp @@ -177,56 +177,60 @@ void RenderWindowFrame(FRAMETYPE frame, UDWORD x, UDWORD y, UDWORD Width, UDWORD } } + BatchedImageDrawRequests imageDrawBatch(true); // defer drawing + if (Frame->TopLeft >= 0) { WTopLeft = (SWORD)iV_GetImageWidth(IntImages, Frame->TopLeft); HTopLeft = (SWORD)iV_GetImageHeight(IntImages, Frame->TopLeft); - iV_DrawImage(IntImages, Frame->TopLeft, x, y, modelViewProjectionMatrix); + iV_DrawImage(IntImages, Frame->TopLeft, x, y, modelViewProjectionMatrix, &imageDrawBatch); } if (Frame->TopRight >= 0) { WTopRight = (SWORD)iV_GetImageWidth(IntImages, Frame->TopRight); HTopRight = (SWORD)iV_GetImageHeight(IntImages, Frame->TopRight); - iV_DrawImage(IntImages, Frame->TopRight, x + Width - WTopRight, y, modelViewProjectionMatrix); + iV_DrawImage(IntImages, Frame->TopRight, x + Width - WTopRight, y, modelViewProjectionMatrix, &imageDrawBatch); } if (Frame->BottomRight >= 0) { WBottomRight = (SWORD)iV_GetImageWidth(IntImages, Frame->BottomRight); HBottomRight = (SWORD)iV_GetImageHeight(IntImages, Frame->BottomRight); - iV_DrawImage(IntImages, Frame->BottomRight, x + Width - WBottomRight, y + Height - HBottomRight, modelViewProjectionMatrix); + iV_DrawImage(IntImages, Frame->BottomRight, x + Width - WBottomRight, y + Height - HBottomRight, modelViewProjectionMatrix, &imageDrawBatch); } if (Frame->BottomLeft >= 0) { WBottomLeft = (SWORD)iV_GetImageWidth(IntImages, Frame->BottomLeft); HBottomLeft = (SWORD)iV_GetImageHeight(IntImages, Frame->BottomLeft); - iV_DrawImage(IntImages, Frame->BottomLeft, x, y + Height - HBottomLeft, modelViewProjectionMatrix); + iV_DrawImage(IntImages, Frame->BottomLeft, x, y + Height - HBottomLeft, modelViewProjectionMatrix, &imageDrawBatch); } if (Frame->TopEdge >= 0) { iV_DrawImageRepeatX(IntImages, Frame->TopEdge, x + iV_GetImageWidth(IntImages, Frame->TopLeft), y, - Width - WTopLeft - WTopRight, modelViewProjectionMatrix); + Width - WTopLeft - WTopRight, modelViewProjectionMatrix, false, &imageDrawBatch); } if (Frame->BottomEdge >= 0) { iV_DrawImageRepeatX(IntImages, Frame->BottomEdge, x + WBottomLeft, y + Height - iV_GetImageHeight(IntImages, Frame->BottomEdge), - Width - WBottomLeft - WBottomRight, modelViewProjectionMatrix); + Width - WBottomLeft - WBottomRight, modelViewProjectionMatrix, false, &imageDrawBatch); } if (Frame->LeftEdge >= 0) { - iV_DrawImageRepeatY(IntImages, Frame->LeftEdge, x, y + HTopLeft, Height - HTopLeft - HBottomLeft, modelViewProjectionMatrix); + iV_DrawImageRepeatY(IntImages, Frame->LeftEdge, x, y + HTopLeft, Height - HTopLeft - HBottomLeft, modelViewProjectionMatrix, &imageDrawBatch); } if (Frame->RightEdge >= 0) { iV_DrawImageRepeatY(IntImages, Frame->RightEdge, x + Width - iV_GetImageWidth(IntImages, Frame->RightEdge), y + HTopRight, - Height - HTopRight - HBottomRight, modelViewProjectionMatrix); + Height - HTopRight - HBottomRight, modelViewProjectionMatrix, &imageDrawBatch); } + + imageDrawBatch.draw(true); } IntListTabWidget::IntListTabWidget(WIDGET *parent)