From 9abb51fce0cca32ebe267c4797363d99520c2a0a Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Thu, 25 Oct 2012 21:43:32 +0300 Subject: Add initial version of mobile OpenGL backend. --- src/CMakeLists.txt | 2 + src/Makefile.am | 4 +- src/graphics.cpp | 2 +- src/graphicsmanager.cpp | 6 + src/graphicsvertexes.cpp | 34 +- src/graphicsvertexes.h | 16 +- src/gui/setup_video.cpp | 7 +- src/mobileopenglgraphics.cpp | 1180 +++++++++++++++++++++++++++++++++++ src/mobileopenglgraphics.h | 204 ++++++ src/normalopenglgraphics.cpp | 2 +- src/normalopenglgraphics.h | 6 +- src/resources/image.cpp | 1 + src/resources/image.h | 1 + src/resources/openglimagehelper.cpp | 21 +- src/resources/subimage.cpp | 1 + src/safeopenglgraphics.h | 4 +- 16 files changed, 1474 insertions(+), 17 deletions(-) create mode 100644 src/mobileopenglgraphics.cpp create mode 100644 src/mobileopenglgraphics.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 96ac9e95d..77b9792b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -601,6 +601,8 @@ SET(SRCS maplayer.h mgl.cpp mgl.h + mobileopenglgraphics.cpp + mobileopenglgraphics.h normalopenglgraphics.cpp normalopenglgraphics.h particle.cpp diff --git a/src/Makefile.am b/src/Makefile.am index b86617e23..09c47c21e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -605,7 +605,9 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ maplayer.h \ mgl.cpp \ mgl.h \ - normalopenglgraphics.cpp\ + mobileopenglgraphics.cpp \ + mobileopenglgraphics.h \ + normalopenglgraphics.cpp \ normalopenglgraphics.h \ particle.cpp \ particle.h \ diff --git a/src/graphics.cpp b/src/graphics.cpp index 9f45899f5..4c1d4e832 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -174,7 +174,7 @@ bool Graphics::setOpenGLMode() bool rectTex = graphicsManager.supportExtension( "GL_ARB_texture_rectangle"); if (rectTex && OpenGLImageHelper::getInternalTextureType() == 4 - && config.getBoolValue("rectangulartextures") + && getOpenGL() != 3 && config.getBoolValue("rectangulartextures") && !graphicsManager.isUseTextureSampler()) { logger->log1("using GL_ARB_texture_rectangle"); diff --git a/src/graphicsmanager.cpp b/src/graphicsmanager.cpp index f03d784a1..4c97ea327 100644 --- a/src/graphicsmanager.cpp +++ b/src/graphicsmanager.cpp @@ -219,6 +219,12 @@ void GraphicsManager::initGraphics(bool noOpenGL) mainGraphics = new SafeOpenGLGraphics; mUseTextureSampler = false; break; + case 3: + imageHelper = new OpenGLImageHelper; + sdlImageHelper = new SDLImageHelper; + mainGraphics = new MobileOpenGLGraphics; + mUseTextureSampler = false; + break; }; mUseAtlases = imageHelper->useOpenGL() && config.getBoolValue("useAtlases"); diff --git a/src/graphicsvertexes.cpp b/src/graphicsvertexes.cpp index 407d5ef0c..aefe594fd 100644 --- a/src/graphicsvertexes.cpp +++ b/src/graphicsvertexes.cpp @@ -25,6 +25,7 @@ #include "debug.h" #ifdef USE_OPENGL +unsigned int vertexBufSize = 500; int GraphicsVertexes::mUseOpenGL = 0; #endif @@ -43,10 +44,12 @@ NormalOpenGLGraphicsVertexes::NormalOpenGLGraphicsVertexes() : ptr(0), mFloatTexArray(nullptr), mIntTexArray(nullptr), - mIntVertArray(nullptr) + mIntVertArray(nullptr), + mShortVertArray(nullptr) { mFloatTexPool.reserve(30); mIntVertPool.reserve(30); + mShortVertPool.reserve(30); mIntTexPool.reserve(30); mVp.reserve(30); } @@ -72,6 +75,13 @@ void NormalOpenGLGraphicsVertexes::clear() } mIntVertPool.clear(); + for (std::vector::iterator it = mShortVertPool.begin(); + it != mShortVertPool.end(); ++ it) + { + delete [] (*it); + } + mShortVertPool.clear(); + for (std::vector::iterator it = mIntTexPool.begin(); it != mIntTexPool.end(); ++ it) { @@ -86,6 +96,7 @@ void NormalOpenGLGraphicsVertexes::clear() delete []mFloatTexArray; delete []mIntTexArray; delete []mIntVertArray; + delete []mShortVertArray; } } @@ -108,6 +119,13 @@ GLint *NormalOpenGLGraphicsVertexes::switchIntVertArray() return mIntVertArray; } +GLshort *NormalOpenGLGraphicsVertexes::switchShortVertArray() +{ + mShortVertArray = new GLshort[vertexBufSize * 4 + 30]; + mShortVertPool.push_back(mShortVertArray); + return mShortVertArray; +} + GLint *NormalOpenGLGraphicsVertexes::switchIntTexArray() { mIntTexArray = new GLint[vertexBufSize * 4 + 30]; @@ -169,6 +187,20 @@ GLint *NormalOpenGLGraphicsVertexes::continueIntVertArray() return mIntVertArray; } +GLshort *NormalOpenGLGraphicsVertexes::continueShortVertArray() +{ + if (mShortVertPool.empty()) + { + mShortVertArray = new GLshort[vertexBufSize * 4 + 30]; + mShortVertPool.push_back(mShortVertArray); + } + else + { + mShortVertArray = mShortVertPool.back(); + } + return mShortVertArray; +} + GLint *NormalOpenGLGraphicsVertexes::continueIntTexArray() { if (mIntTexPool.empty()) diff --git a/src/graphicsvertexes.h b/src/graphicsvertexes.h index 789e9fd34..6a2e30664 100644 --- a/src/graphicsvertexes.h +++ b/src/graphicsvertexes.h @@ -37,8 +37,9 @@ #include -#include "safeopenglgraphics.h" +#include "mobileopenglgraphics.h" #include "normalopenglgraphics.h" +#include "safeopenglgraphics.h" #endif #include "resources/image.h" @@ -85,12 +86,17 @@ class NormalOpenGLGraphicsVertexes final GLint *switchIntTexArray(); + GLshort *switchShortVertArray(); + std::vector *getFloatTexPool() { return &mFloatTexPool; } std::vector *getIntVertPool() { return &mIntVertPool; } + std::vector *getShortVertPool() + { return &mShortVertPool; } + std::vector *getIntTexPool() { return &mIntTexPool; } @@ -100,6 +106,8 @@ class NormalOpenGLGraphicsVertexes final GLint *continueIntVertArray(); + GLshort *continueShortVertArray(); + GLint *continueIntTexArray(); int continueVp(); @@ -118,9 +126,11 @@ class NormalOpenGLGraphicsVertexes final GLfloat *mFloatTexArray; GLint *mIntTexArray; GLint *mIntVertArray; + GLshort *mShortVertArray; std::vector mVp; std::vector mFloatTexPool; std::vector mIntVertPool; + std::vector mShortVertPool; std::vector mIntTexPool; }; #endif @@ -203,4 +213,8 @@ class GraphicsVertexes final #endif }; +#ifdef USE_OPENGL +extern unsigned int vertexBufSize; +#endif + #endif // GRAPHICSVERTEXES_H diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index f722dbae8..9eaf5be56 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -193,11 +193,12 @@ int ModeListModel::getIndexOf(const std::string &widthXHeightMode) return -1; } -const char *OPENGL_NAME[3] = +const char *OPENGL_NAME[4] = { N_("Software"), N_("Fast OpenGL"), N_("Safe OpenGL"), + N_("Mobile OpenGL"), }; class OpenGLListModel final : public gcn::ListModel @@ -207,7 +208,7 @@ public: { } virtual int getNumberOfElements() - { return 3; } + { return 4; } virtual std::string getElementAt(int i) { @@ -566,7 +567,7 @@ void Setup_Video::action(const gcn::ActionEvent &event) if (test) { const int val = test->getConfig().getValueInt("opengl", -1); - if (val >= 0 && val <= 2) + if (val >= 0 && val <= 3) mOpenGLDropDown->setSelected(val); delete test; } diff --git a/src/mobileopenglgraphics.cpp b/src/mobileopenglgraphics.cpp new file mode 100644 index 000000000..1cc1fae8a --- /dev/null +++ b/src/mobileopenglgraphics.cpp @@ -0,0 +1,1180 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "main.h" + +#ifdef USE_OPENGL + +#include "mobileopenglgraphics.h" + +#include "configuration.h" +#include "graphicsmanager.h" +#include "graphicsvertexes.h" +#include "logger.h" + +#include "resources/image.h" +#include "resources/openglimagehelper.h" + +#include "utils/stringutils.h" + +#include + +#include "debug.h" + +GLuint MobileOpenGLGraphics::mLastImage = 0; + +//unsigned int vertexBufSize = 500; + +MobileOpenGLGraphics::MobileOpenGLGraphics(): + mFloatTexArray(nullptr), + mIntTexArray(nullptr), + mIntVertArray(nullptr), + mShortVertArray(nullptr), + mAlpha(false), + mTexture(false), + mIsByteColor(false), + mFloatColor(1.0f), + mMaxVertices(500), +#ifdef DEBUG_BIND_TEXTURE + mColorAlpha(false), + mOldTextureId(0) +#else + mColorAlpha(false) +#endif +{ + mOpenGL = 3; + mName = "mobile OpenGL"; +} + +MobileOpenGLGraphics::~MobileOpenGLGraphics() +{ + delete [] mFloatTexArray; + delete [] mIntTexArray; + delete [] mIntVertArray; + delete [] mShortVertArray; +} + +void MobileOpenGLGraphics::initArrays() +{ + mMaxVertices = graphicsManager.getMaxVertices(); + if (mMaxVertices < 500) + mMaxVertices = 500; + else if (mMaxVertices > 1024) + mMaxVertices = 1024; + + // need alocate small size, after if limit reached reallocate to double size + vertexBufSize = mMaxVertices; + mFloatTexArray = new GLfloat[mMaxVertices * 4 + 30]; + mIntTexArray = new GLint[mMaxVertices * 4 + 30]; + mIntVertArray = new GLint[mMaxVertices * 4 + 30]; + mShortVertArray = new GLshort[mMaxVertices * 4 + 30]; +} + +bool MobileOpenGLGraphics::setVideoMode(const int w, const int h, + const int bpp, const bool fs, + const bool hwaccel, const bool resize, + const bool noFrame) +{ + setMainFlags(w, h, bpp, fs, hwaccel, resize, noFrame); + + return setOpenGLMode(); +} + +static inline void drawQuad(const Image *image, + int srcX, int srcY, int dstX, int dstY, + int width, int height) +{ +// if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + // Find OpenGL normalized texture coordinates. + const float texX1 = static_cast(srcX) / + static_cast(image->mTexWidth); + const float texY1 = static_cast(srcY) / + static_cast(image->mTexHeight); + const float texX2 = static_cast(srcX + width) / + static_cast(image->mTexWidth); + const float texY2 = static_cast(srcY + height) / + static_cast(image->mTexHeight); + + GLfloat tex[] = + { + texX1, texY1, + texX2, texY1, + texX1, texY2, + texX2, texY2 + }; + + GLshort vert[] = + { + static_cast(dstX), static_cast(dstY), + static_cast(dstX + width), static_cast(dstY), + static_cast(dstX), static_cast(dstY + height), + static_cast(dstX + width), + static_cast(dstY + height) + }; + + glVertexPointer(2, GL_SHORT, 0, &vert); + glTexCoordPointer(2, GL_FLOAT, 0, &tex); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } +} + +static inline void drawRescaledQuad(const Image *const image, + int srcX, int srcY, int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight) +{ +// if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + // Find OpenGL normalized texture coordinates. + const float texX1 = static_cast(srcX) / + static_cast(image->mTexWidth); + const float texY1 = static_cast(srcY) / + static_cast(image->mTexHeight); + const float texX2 = static_cast(srcX + width) / + static_cast(image->mTexWidth); + const float texY2 = static_cast(srcY + height) / + static_cast(image->mTexHeight); + + GLfloat tex[] = + { + texX1, texY1, + texX2, texY1, + texX1, texY2, + texX2, texY2 + }; + + GLshort vert[] = + { + static_cast(dstX), static_cast(dstY), + static_cast(dstX + desiredWidth), + static_cast(dstY), + static_cast(dstX), static_cast( + dstY + desiredHeight), + static_cast(dstX + desiredWidth), + static_cast(dstY + desiredHeight) + }; + glVertexPointer(2, GL_SHORT, 0, &vert); + glTexCoordPointer(2, GL_FLOAT, 0, &tex); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } +} + + +bool MobileOpenGLGraphics::drawImage2(const Image *const image, + int srcX, int srcY, + int dstX, int dstY, + const int width, const int height, + const bool useColor) +{ + if (!image) + return false; + + srcX += image->mBounds.x; + srcY += image->mBounds.y; + + if (!useColor) + setColorAlpha(image->mAlpha); + +#ifdef DEBUG_BIND_TEXTURE + debugBindTexture(image); +#endif + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + drawQuad(image, srcX, srcY, dstX, dstY, width, height); + + return true; +} + +bool MobileOpenGLGraphics::drawRescaledImage(Image *const image, int srcX, + int srcY, int dstX, int dstY, + const int width, const int height, + const int desiredWidth, + const int desiredHeight, + const bool useColor) +{ + return drawRescaledImage(image, srcX, srcY, + dstX, dstY, + width, height, + desiredWidth, desiredHeight, + useColor, true); +} + +bool MobileOpenGLGraphics::drawRescaledImage(Image *const image, int srcX, + int srcY, int dstX, int dstY, + const int width, const int height, + const int desiredWidth, + const int desiredHeight, + const bool useColor, + bool smooth) +{ + if (!image) + return false; + + // Just draw the image normally when no resizing is necessary, + if (width == desiredWidth && height == desiredHeight) + { + return drawImage2(image, srcX, srcY, dstX, dstY, + width, height, useColor); + } + + // When the desired image is smaller than the current one, + // disable smooth effect. + if (width > desiredWidth && height > desiredHeight) + smooth = false; + + srcX += image->mBounds.x; + srcY += image->mBounds.y; + + if (!useColor) + setColorAlpha(image->mAlpha); + +#ifdef DEBUG_BIND_TEXTURE + debugBindTexture(image); +#endif + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + // Draw a textured quad. + drawRescaledQuad(image, srcX, srcY, dstX, dstY, width, height, + desiredWidth, desiredHeight); + + if (smooth) // A basic smooth effect... + { + setColorAlpha(0.2f); + drawRescaledQuad(image, srcX, srcY, dstX - 1, dstY - 1, width, height, + desiredWidth + 1, desiredHeight + 1); + drawRescaledQuad(image, srcX, srcY, dstX + 1, dstY + 1, width, height, + desiredWidth - 1, desiredHeight - 1); + + drawRescaledQuad(image, srcX, srcY, dstX + 1, dstY, width, height, + desiredWidth - 1, desiredHeight); + drawRescaledQuad(image, srcX, srcY, dstX, dstY + 1, width, height, + desiredWidth, desiredHeight - 1); + } + + return true; +} + +void MobileOpenGLGraphics::drawImagePattern(const Image *const image, + const int x, const int y, + const int w, const int h) +{ + 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); + + setColorAlpha(image->mAlpha); + +#ifdef DEBUG_BIND_TEXTURE + debugBindTexture(image); +#endif + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + unsigned int vp = 0; + const unsigned int vLimit = mMaxVertices * 4; + // Draw a set of textured rectangles +// if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + float texX1 = static_cast(srcX) / tw; + 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; + 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; + + mFloatTexArray[vp + 0] = texX1; //1 + mFloatTexArray[vp + 1] = texY1; + + mFloatTexArray[vp + 2] = texX2; //2 + mFloatTexArray[vp + 3] = texY1; + + mFloatTexArray[vp + 4] = texX2; //3 + mFloatTexArray[vp + 5] = texY2; + + mFloatTexArray[vp + 6] = texX1; //1 + mFloatTexArray[vp + 7] = texY1; + + mFloatTexArray[vp + 8] = texX1; //4 + mFloatTexArray[vp + 9] = texY2; + + mFloatTexArray[vp + 10] = texX2; //3 + mFloatTexArray[vp + 11] = texY2; + + mShortVertArray[vp + 0] = dstX; + mShortVertArray[vp + 1] = dstY; + + mShortVertArray[vp + 2] = dstX + width; + mShortVertArray[vp + 3] = dstY; + + mShortVertArray[vp + 4] = dstX + width; + mShortVertArray[vp + 5] = dstY + height; + + mShortVertArray[vp + 6] = dstX; + mShortVertArray[vp + 7] = dstY; + + mShortVertArray[vp + 8] = dstX; + mShortVertArray[vp + 9] = dstY + height; + + mShortVertArray[vp + 10] = dstX + width; + mShortVertArray[vp + 11] = dstY + height; + + vp += 12; + if (vp >= vLimit) + { + drawTriangleArrayfs(vp); + vp = 0; + } + } + } + if (vp > 0) + drawTriangleArrayfs(vp); + } +} + +void MobileOpenGLGraphics::drawRescaledImagePattern(const Image *const image, + const int x, const int y, + const int w, const int h, + const int scaledWidth, + const int scaledHeight) +{ + if (!image) + return; + + if (scaledWidth == 0 || scaledHeight == 0) + return; + + const int srcX = image->mBounds.x; + const int srcY = image->mBounds.y; + + const int iw = image->getWidth(); + const int ih = image->getHeight(); + if (iw == 0 || ih == 0) + return; + + setColorAlpha(image->mAlpha); + +#ifdef DEBUG_BIND_TEXTURE + debugBindTexture(image); +#endif + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + unsigned int vp = 0; + const unsigned int vLimit = mMaxVertices * 4; + + // Draw a set of textured rectangles +// if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + const float tw = static_cast(image->mTexWidth); + const float th = static_cast(image->mTexHeight); + + const float texX1 = static_cast(srcX) / tw; + const float texY1 = static_cast(srcY) / th; + + const float tFractionW = iw / tw; + const float tFractionH = ih / th; + + for (int py = 0; py < h; py += scaledHeight) + { + const int height = (py + scaledHeight >= h) + ? h - py : scaledHeight; + const int dstY = y + py; + for (int px = 0; px < w; px += scaledWidth) + { + int width = (px + scaledWidth >= w) ? w - px : scaledWidth; + int dstX = x + px; + const float visibleFractionW = static_cast(width) + / scaledWidth; + const float visibleFractionH = static_cast(height) + / scaledHeight; + + const float texX2 = texX1 + tFractionW * visibleFractionW; + const float texY2 = texY1 + tFractionH * visibleFractionH; + + mFloatTexArray[vp + 0] = texX1; + mFloatTexArray[vp + 1] = texY1; + + mFloatTexArray[vp + 2] = texX2; + mFloatTexArray[vp + 3] = texY1; + + mFloatTexArray[vp + 4] = texX2; + mFloatTexArray[vp + 5] = texY2; + + mFloatTexArray[vp + 6] = texX1; + mFloatTexArray[vp + 7] = texY1; + + mFloatTexArray[vp + 8] = texX1; + mFloatTexArray[vp + 9] = texY2; + + mFloatTexArray[vp + 10] = texX2; + mFloatTexArray[vp + 11] = texY2; + + + mShortVertArray[vp + 0] = dstX; + mShortVertArray[vp + 1] = dstY; + + mShortVertArray[vp + 2] = dstX + width; + mShortVertArray[vp + 3] = dstY; + + mShortVertArray[vp + 4] = dstX + width; + mShortVertArray[vp + 5] = dstY + height; + + mShortVertArray[vp + 6] = dstX; + mShortVertArray[vp + 7] = dstY; + + mShortVertArray[vp + 8] = dstX; + mShortVertArray[vp + 9] = dstY + height; + + mShortVertArray[vp + 10] = dstX + width; + mShortVertArray[vp + 11] = dstY + height; + + vp += 12; + if (vp >= vLimit) + { + drawTriangleArrayfs(vp); + vp = 0; + } + } + } + if (vp > 0) + drawTriangleArrayfs(vp); + } +} + +void MobileOpenGLGraphics::drawImagePattern2(GraphicsVertexes *const vert, + const Image *const image) +{ + if (!image) + return; + + setColorAlpha(image->mAlpha); +#ifdef DEBUG_BIND_TEXTURE + debugBindTexture(image); +#endif + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); + setTexturingAndBlending(true); + + drawVertexes(vert->getOGL()); +} + +inline void MobileOpenGLGraphics::drawVertexes(NormalOpenGLGraphicsVertexes + &ogl) +{ + std::vector &shortVertPool = ogl.mShortVertPool; + std::vector::const_iterator iv; + std::vector::const_iterator iv_end = shortVertPool.end(); + std::vector &vp = ogl.mVp; + std::vector::const_iterator ivp; + std::vector::const_iterator ivp_end = vp.end(); + + // Draw a set of textured rectangles +// if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) + { + std::vector &floatTexPool = ogl.mFloatTexPool; + std::vector::const_iterator ft; + std::vector::const_iterator ft_end = floatTexPool.end(); + + for (iv = shortVertPool.begin(), ft = floatTexPool.begin(), + ivp = vp.begin(); + iv != iv_end, ft != ft_end, + ivp != ivp_end; + ++ iv, ++ ft, ++ ivp) + { + drawTriangleArrayfs(*iv, *ft, *ivp); + } + } +} + +void MobileOpenGLGraphics::calcImagePattern(GraphicsVertexes *const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) +{ + if (!image) + { + vert->incPtr(1); + 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) + { + vert->incPtr(1); + return; + } + + const float tw = static_cast(image->mTexWidth); + const float th = static_cast(image->mTexHeight); + + unsigned int vp = 0; + const unsigned int vLimit = mMaxVertices * 4; + + NormalOpenGLGraphicsVertexes &ogl = vert->getOGL(); + ogl.init(); + + // 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.switchFloatTexArray(); + GLshort *shortVertArray = ogl.switchShortVertArray(); + + 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); + vert->incPtr(1); +} + +void MobileOpenGLGraphics::calcTile(ImageVertexes *const vert, + const Image *const image, + int dstX, int dstY) +{ + if (!vert || !image) + return; + + const int srcX = image->mBounds.x; + const int srcY = image->mBounds.y; + + const int w = image->mBounds.w; + const int h = image->mBounds.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; + + NormalOpenGLGraphicsVertexes &ogl = vert->ogl; + +// std::vector *vps = ogl.getVp(); + 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; + + float texX2 = static_cast(srcX + w) / tw; + float texY2 = static_cast(srcY + h) / th; + + GLfloat *floatTexArray = ogl.continueFloatTexArray(); + GLshort *shortVertArray = ogl.continueShortVertArray(); + + 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 + w; + shortVertArray[vp + 3] = dstY; + + shortVertArray[vp + 4] = dstX + w; + shortVertArray[vp + 5] = dstY + h; + + shortVertArray[vp + 6] = dstX; + shortVertArray[vp + 7] = dstY; + + shortVertArray[vp + 8] = dstX; + shortVertArray[vp + 9] = dstY + h; + + shortVertArray[vp + 10] = dstX + w; + shortVertArray[vp + 11] = dstY + h; + + vp += 12; + if (vp >= vLimit) + { + ogl.switchFloatTexArray(); + ogl.switchShortVertArray(); + ogl.switchVp(vp); + vp = 0; + } + } + ogl.switchVp(vp); +} + +void MobileOpenGLGraphics::drawTile(ImageVertexes *const vert) +{ + if (!vert) + return; + Image *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::updateScreen() +{ +// glFlush(); +// glFinish(); + SDL_GL_SwapBuffers(); +// may be need clear? +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); +} + +void MobileOpenGLGraphics::_beginDraw() +{ + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + +#ifdef ANDROID + glOrthof(0.0, static_cast(mTarget->w), + static_cast(mTarget->h), 0.0, -1.0, 1.0); +#else + glOrtho(0.0, static_cast(mTarget->w), + static_cast(mTarget->h), 0.0, -1.0, 1.0); +#endif + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glEnable(GL_SCISSOR_TEST); + glDisable(GL_DITHER); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glEnableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + +#ifndef ANDROID + glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST); +#ifndef __MINGW32__ + glHint(GL_TEXTURE_COMPRESSION_HINT, GL_FASTEST); +#endif +#endif + +// glScalef(0.5f, 0.5f, 0.5f); + + pushClipArea(gcn::Rectangle(0, 0, mTarget->w, mTarget->h)); +} + +void MobileOpenGLGraphics::_endDraw() +{ + popClipArea(); +} + +void MobileOpenGLGraphics::prepareScreenshot() +{ + if (config.getBoolValue("usefbo")) + graphicsManager.createFBO(mTarget->w, mTarget->h, &mFbo); +} + +SDL_Surface* MobileOpenGLGraphics::getScreenshot() +{ + const int h = mTarget->h; + const int w = mTarget->w - (mTarget->w % 4); + GLint pack = 1; + + SDL_Surface *screenshot = SDL_CreateRGBSurface( + SDL_SWSURFACE, + w, h, 24, + 0xff0000, 0x00ff00, 0x0000ff, 0x000000); + + if (!screenshot) + return nullptr; + + if (SDL_MUSTLOCK(screenshot)) + SDL_LockSurface(screenshot); + + // Grap the pixel buffer and write it to the SDL surface + glGetIntegerv(GL_PACK_ALIGNMENT, &pack); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, screenshot->pixels); + + // Flip the screenshot, as OpenGL has 0,0 in bottom left + unsigned int lineSize = 3 * w; + GLubyte* buf = static_cast(malloc(lineSize)); + + for (int i = 0; i < (h / 2); i++) + { + GLubyte *top = static_cast( + screenshot->pixels) + lineSize * i; + GLubyte *bot = static_cast( + screenshot->pixels) + lineSize * (h - 1 - i); + + memcpy(buf, top, lineSize); + memcpy(top, bot, lineSize); + memcpy(bot, buf, lineSize); + } + + free(buf); + + if (config.getBoolValue("usefbo")) + graphicsManager.deleteFBO(&mFbo); + + glPixelStorei(GL_PACK_ALIGNMENT, pack); + + if (SDL_MUSTLOCK(screenshot)) + SDL_UnlockSurface(screenshot); + + return screenshot; +} + +bool MobileOpenGLGraphics::pushClipArea(gcn::Rectangle area) +{ + int transX = 0; + int transY = 0; + + if (!mClipStack.empty()) + { + const gcn::ClipRectangle &clipArea = mClipStack.top(); + transX = -clipArea.xOffset; + transY = -clipArea.yOffset; + } + + bool result = gcn::Graphics::pushClipArea(area); + + const gcn::ClipRectangle &clipArea = mClipStack.top(); + transX += clipArea.xOffset; + transY += clipArea.yOffset; + + glPushMatrix(); + if (transX || transY) + { + glTranslatef(static_cast(transX), + static_cast(transY), 0); + } + glScissor(clipArea.x, mTarget->h - clipArea.y - clipArea.height, + clipArea.width, clipArea.height); + + return result; +} + +void MobileOpenGLGraphics::popClipArea() +{ + gcn::Graphics::popClipArea(); + + if (mClipStack.empty()) + return; + + glPopMatrix(); + const gcn::ClipRectangle &clipArea = mClipStack.top(); + glScissor(clipArea.x, mTarget->h - clipArea.y - clipArea.height, + clipArea.width, clipArea.height); +} + +void MobileOpenGLGraphics::setColor(const gcn::Color& color) +{ + mColor = color; + mColorAlpha = (color.a != 255); +} + +void MobileOpenGLGraphics::drawPoint(int x, int y) +{ + setTexturingAndBlending(false); + restoreColor(); + +#ifdef ANDROID + // TODO need fix +#else + glBegin(GL_POINTS); + glVertex2i(x, y); + glEnd(); +#endif +} + +void MobileOpenGLGraphics::drawLine(int x1, int y1, int x2, int y2) +{ + setTexturingAndBlending(false); + restoreColor(); + + mShortVertArray[0] = static_cast(x1); + mShortVertArray[1] = static_cast(y1); + mShortVertArray[2] = static_cast(x2); + mShortVertArray[3] = static_cast(y2); + + drawLineArrays(4); +} + +void MobileOpenGLGraphics::drawRectangle(const gcn::Rectangle& rect) +{ + drawRectangle(rect, false); +} + +void MobileOpenGLGraphics::fillRectangle(const gcn::Rectangle& rect) +{ + drawRectangle(rect, true); +} + +void MobileOpenGLGraphics::setTargetPlane(int width A_UNUSED, + int height A_UNUSED) +{ +} + +void MobileOpenGLGraphics::setTexturingAndBlending(bool enable) +{ + if (enable) + { + if (!mTexture) + { + glEnable(OpenGLImageHelper::mTextureType); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + mTexture = true; + } + + if (!mAlpha) + { + glEnable(GL_BLEND); + mAlpha = true; + } + } + else + { + mLastImage = 0; + if (mAlpha && !mColorAlpha) + { + glDisable(GL_BLEND); + mAlpha = false; + } + else if (!mAlpha && mColorAlpha) + { + glEnable(GL_BLEND); + mAlpha = true; + } + + if (mTexture) + { + glDisable(OpenGLImageHelper::mTextureType); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + mTexture = false; + } + } +} + +void MobileOpenGLGraphics::drawRectangle(const gcn::Rectangle& rect, + bool filled) +{ + setTexturingAndBlending(false); + restoreColor(); + + const GLshort x = static_cast(rect.x); + const GLshort y = static_cast(rect.y); + const GLshort width = static_cast(rect.width); + const GLshort height = static_cast(rect.height); + const GLshort xw = static_cast(rect.x + width); + const GLshort yh = static_cast(rect.y + height); + + if (filled) + { + GLshort vert[] = + { + x, y, + xw, y, + x, yh, + xw, yh + }; + + glVertexPointer(2, GL_SHORT, 0, &vert); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + else + { + GLshort vert[] = + { + x, y, + xw, y, + xw, yh, + x, yh + }; + + glVertexPointer(2, GL_SHORT, 0, &vert); + glDrawArrays(GL_LINE_LOOP, 0, 4); + } +} + +bool MobileOpenGLGraphics::drawNet(const int x1, const int y1, + const int x2, const int y2, + const int width, const int height) +{ + unsigned int vp = 0; + const unsigned int vLimit = mMaxVertices * 4; + + setTexturingAndBlending(false); + restoreColor(); + + const GLshort xs1 = static_cast(x1); + const GLshort xs2 = static_cast(x2); + const GLshort ys1 = static_cast(y1); + const GLshort ys2 = static_cast(y2); + + for (short y = y1; y < y2; y += height) + { + mShortVertArray[vp + 0] = xs1; + mShortVertArray[vp + 1] = y; + + mShortVertArray[vp + 2] = xs2; + mShortVertArray[vp + 3] = y; + + vp += 4; + if (vp >= vLimit) + { + drawLineArrays(vp); + vp = 0; + } + } + + for (short x = x1; x < x2; x += width) + { + mShortVertArray[vp + 0] = x; + mShortVertArray[vp + 1] = ys1; + + mShortVertArray[vp + 2] = x; + mShortVertArray[vp + 3] = ys2; + + vp += 4; + if (vp >= vLimit) + { + drawLineArrays(vp); + vp = 0; + } + } + + if (vp > 0) + drawLineArrays(vp); + + return true; +} + +void MobileOpenGLGraphics::bindTexture(GLenum target, GLuint texture) +{ + if (mLastImage != texture) + { + mLastImage = texture; + glBindTexture(target, texture); + } +} + +inline void MobileOpenGLGraphics::drawTriangleArrayfs(int size) +{ + glVertexPointer(2, GL_SHORT, 0, mShortVertArray); + glTexCoordPointer(2, GL_FLOAT, 0, mFloatTexArray); + + glDrawArrays(GL_TRIANGLES, 0, size / 2); +} + +inline void MobileOpenGLGraphics::drawTriangleArrayfs(GLshort *const + shortVertArray, + GLfloat *const + floatTexArray, + const int size) +{ + glVertexPointer(2, GL_SHORT, 0, shortVertArray); + glTexCoordPointer(2, GL_FLOAT, 0, floatTexArray); + + glDrawArrays(GL_TRIANGLES, 0, size / 2); +} + +inline void MobileOpenGLGraphics::drawLineArrays(int size) +{ + glVertexPointer(2, GL_SHORT, 0, mShortVertArray); + + glDrawArrays(GL_LINES, 0, size / 2); +} + +void MobileOpenGLGraphics::dumpSettings() +{ + GLint test[1000]; + logger->log("\n\n"); + logger->log("start opengl dump"); + for (int f = 0; f < 65535; f ++) + { + test[0] = 0; + test[1] = 0; + test[2] = 0; + test[3] = 0; + glGetIntegerv(f, &test[0]); + if (test[0] || test[1] || test[2] || test[3]) + { + logger->log("\n%d = %d, %d, %d, %d", f, + test[0], test[1], test[2], test[3]); + } + } +} + +void MobileOpenGLGraphics::setColorAlpha(const float alpha) +{ + if (!mIsByteColor && mFloatColor == alpha) + return; + + glColor4f(1.0f, 1.0f, 1.0f, alpha); + mIsByteColor = false; + mFloatColor = alpha; +} + +void MobileOpenGLGraphics::restoreColor() +{ + if (mIsByteColor && mByteColor == mColor) + return; + + glColor4ub(static_cast(mColor.r), + static_cast(mColor.g), + static_cast(mColor.b), + static_cast(mColor.a)); + mIsByteColor = true; + mByteColor = mColor; +} + +#ifdef DEBUG_BIND_TEXTURE +void MobileOpenGLGraphics::debugBindTexture(const Image *image) +{ + const std::string texture = image->getIdPath(); + if (mOldTexture != texture) + { + if ((!mOldTexture.empty() || !texture.empty()) + && mOldTextureId != image->mGLImage) + { + logger->log("bind: %s (%d) to %s (%d)", mOldTexture.c_str(), + mOldTextureId, texture.c_str(), image->mGLImage); + } + mOldTextureId = image->mGLImage; + mOldTexture = texture; + } +} +#else +void MobileOpenGLGraphics::debugBindTexture(const Image *image A_UNUSED) +{ +} +#endif + +#endif // USE_OPENGL diff --git a/src/mobileopenglgraphics.h b/src/mobileopenglgraphics.h new file mode 100644 index 000000000..350c21a59 --- /dev/null +++ b/src/mobileopenglgraphics.h @@ -0,0 +1,204 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef MOBILEOPENGLGRAPHICS_H +#define MOBILEOPENGLGRAPHICS_H + +#include "main.h" +#ifdef USE_OPENGL + +#include "localconsts.h" +#include "graphics.h" + +#include "resources/fboinfo.h" + +#ifdef ANDROID +#include +#include +#include +#else +#define GL_GLEXT_PROTOTYPES 1 +#include +#include +#endif + +#include + +class NormalOpenGLGraphicsVertexes; + +class MobileOpenGLGraphics final : public Graphics +{ + public: + MobileOpenGLGraphics(); + + A_DELETE_COPY(MobileOpenGLGraphics) + + ~MobileOpenGLGraphics(); + + bool setVideoMode(const int w, const int h, const int bpp, + const bool fs, const bool hwaccel, + const bool resize, const bool noFrame) override; + + + /** + * Draws a resclaled version of the image + */ + bool drawRescaledImage(Image *const image, int srcX, int srcY, + int dstX, int dstY, + const int width, const int height, + const int desiredWidth, const int desiredHeight, + const bool useColor) override; + + /** + * Used to get the smooth rescale option over the standard function. + */ + bool drawRescaledImage(Image *const image, int srcX, int srcY, + int dstX, int dstY, + const int width, const int height, + const int desiredWidth, const int desiredHeight, + const bool useColor, bool smooth); + + void drawImagePattern(const Image *const image, + const int x, const int y, + const int w, const int h) override; + + /** + * Draw a pattern based on a rescaled version of the given image... + */ + void drawRescaledImagePattern(const Image *const image, + const int x, const int y, + const int w, const int h, + const int scaledWidth, + const int scaledHeight) override; + + void calcImagePattern(GraphicsVertexes *const vert, + const Image *const image, + const int x, const int y, + const int w, const int h) override; + + void calcTile(ImageVertexes *const vert, const Image *const image, + int x, int y) override; + + void drawTile(ImageVertexes *const vert) override; + + void drawImagePattern2(GraphicsVertexes *const vert, + const Image *const image) override; + + void updateScreen() override; + + void _beginDraw(); + + void _endDraw(); + + bool pushClipArea(gcn::Rectangle area); + + void popClipArea(); + + void setColor(const gcn::Color &color); + + void drawPoint(int x, int y); + + void drawLine(int x1, int y1, int x2, int y2); + + void drawRectangle(const gcn::Rectangle &rect, bool filled); + + void drawRectangle(const gcn::Rectangle &rect); + + void fillRectangle(const gcn::Rectangle &rect); + + void setTargetPlane(int width, int height); + + inline void drawTriangleArrayfs(GLshort *shortVertArray, + GLfloat *floatTexArray, + const int size); + + inline void drawTriangleArrayfs(int size); + + inline void drawLineArrays(int size); + + inline void drawVertexes(NormalOpenGLGraphicsVertexes &ogl); + + void initArrays() override; + + static void dumpSettings(); + + /** + * Takes a screenshot and returns it as SDL surface. + */ + SDL_Surface *getScreenshot() override; + + void prepareScreenshot() override; + + bool drawNet(const int x1, const int y1, const int x2, const int y2, + const int width, const int height) override; + + int getMemoryUsage(); + + void updateTextureFormat(); + + static void bindTexture(GLenum target, GLuint texture); + + static GLuint mLastImage; + + protected: + bool drawImage2(const Image *const image, + int srcX, int srcY, + int dstX, int dstY, + const int width, const int height, + const bool useColor) override; + + void setTexturingAndBlending(bool enable); + + void logString(const char *format, GLenum num); + + void updateMemoryInfo(); + + void debugBindTexture(const Image *image); + + private: + void inline setColorAlpha(float alpha); + + void inline restoreColor(); + + GLfloat *mFloatTexArray; + GLint *mIntTexArray; + GLint *mIntVertArray; + GLshort *mShortVertArray; + bool mAlpha; + bool mTexture; + + bool mIsByteColor; + gcn::Color mByteColor; + float mFloatColor; + int mMaxVertices; + bool mColorAlpha; + FBOInfo mFbo; +#ifdef DEBUG_BIND_TEXTURE + std::string mOldTexture; + unsigned mOldTextureId; +#endif +}; +#endif + +//extern unsigned int vertexBufSize; + +#endif diff --git a/src/normalopenglgraphics.cpp b/src/normalopenglgraphics.cpp index cc0e05b3f..61f58dadf 100644 --- a/src/normalopenglgraphics.cpp +++ b/src/normalopenglgraphics.cpp @@ -42,7 +42,7 @@ GLuint NormalOpenGLGraphics::mLastImage = 0; -unsigned int vertexBufSize = 500; +//unsigned int vertexBufSize = 500; NormalOpenGLGraphics::NormalOpenGLGraphics(): mFloatTexArray(nullptr), diff --git a/src/normalopenglgraphics.h b/src/normalopenglgraphics.h index 35bdf557e..144a5b3ee 100644 --- a/src/normalopenglgraphics.h +++ b/src/normalopenglgraphics.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef OPENGLGRAPHICS_H -#define OPENGLGRAPHICS_H +#ifndef NORMALOPENGLGRAPHICS_H +#define NORMALOPENGLGRAPHICS_H #include "main.h" #ifdef USE_OPENGL @@ -206,6 +206,6 @@ class NormalOpenGLGraphics final : public Graphics }; #endif -extern unsigned int vertexBufSize; +//extern unsigned int vertexBufSize; #endif diff --git a/src/resources/image.cpp b/src/resources/image.cpp index b342edcbf..c71cbdec9 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -26,6 +26,7 @@ #include "resources/resourcemanager.h" #ifdef USE_OPENGL +#include "mobileopenglgraphics.h" #include "normalopenglgraphics.h" #include "safeopenglgraphics.h" #endif diff --git a/src/resources/image.h b/src/resources/image.h index 36404b2b1..87a842aa3 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -64,6 +64,7 @@ class Image : public Resource friend class SDLImageHelper; #ifdef USE_OPENGL friend class AtlasManager; + friend class MobileOpenGLGraphics; friend class NormalOpenGLGraphics; friend class SafeOpenGLGraphics; #endif diff --git a/src/resources/openglimagehelper.cpp b/src/resources/openglimagehelper.cpp index a162ccf59..3f825d9db 100644 --- a/src/resources/openglimagehelper.cpp +++ b/src/resources/openglimagehelper.cpp @@ -29,6 +29,7 @@ #include "graphicsmanager.h" #include "logger.h" #include "mgl.h" +#include "mobileopenglgraphics.h" #include "normalopenglgraphics.h" #include "safeopenglgraphics.h" @@ -215,15 +216,27 @@ Image *OpenGLImageHelper::glLoad(SDL_Surface *tmpImage) GLuint texture; glGenTextures(1, &texture); - if (mUseOpenGL == 1) - NormalOpenGLGraphics::bindTexture(mTextureType, texture); - else if (mUseOpenGL == 2) - SafeOpenGLGraphics::bindTexture(mTextureType, texture); + switch (mUseOpenGL) + { + case 1: + NormalOpenGLGraphics::bindTexture(mTextureType, texture); + break; + case 2: + SafeOpenGLGraphics::bindTexture(mTextureType, texture); + break; + case 3: + MobileOpenGLGraphics::bindTexture(mTextureType, texture); + break; + default: + logger->log("Unknown OpenGL backend: %d", mUseOpenGL); + break; + } if (SDL_MUSTLOCK(tmpImage)) SDL_LockSurface(tmpImage); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + if (!mUseTextureSampler) { if (mBlur) diff --git a/src/resources/subimage.cpp b/src/resources/subimage.cpp index a2d6a8c33..bb63f842a 100644 --- a/src/resources/subimage.cpp +++ b/src/resources/subimage.cpp @@ -23,6 +23,7 @@ #include "resources/subimage.h" #ifdef USE_OPENGL +#include "mobileopenglgraphics.h" #include "normalopenglgraphics.h" #include "safeopenglgraphics.h" #endif diff --git a/src/safeopenglgraphics.h b/src/safeopenglgraphics.h index 81494d5bd..a21dc8505 100644 --- a/src/safeopenglgraphics.h +++ b/src/safeopenglgraphics.h @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -#ifndef OPENGL1GRAPHICS_H -#define OPENGL1GRAPHICS_H +#ifndef SAFEOPENGLGRAPHICS_H +#define SAFEOPENGLGRAPHICS_H #ifdef USE_OPENGL #include "main.h" -- cgit v1.2.3-60-g2f50